Home | History | Annotate | Download | only in default
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "StreamInHAL"
     18 
     19 #include "core/default/StreamIn.h"
     20 #include "core/default/Conversions.h"
     21 #include "core/default/Util.h"
     22 #include "common/all-versions/HidlSupport.h"
     23 
     24 //#define LOG_NDEBUG 0
     25 #define ATRACE_TAG ATRACE_TAG_AUDIO
     26 
     27 #include <android/log.h>
     28 #include <hardware/audio.h>
     29 #include <utils/Trace.h>
     30 #include <memory>
     31 #include <cmath>
     32 
     33 namespace android {
     34 namespace hardware {
     35 namespace audio {
     36 namespace CPP_VERSION {
     37 namespace implementation {
     38 
     39 namespace {
     40 
     41 class ReadThread : public Thread {
     42    public:
     43     // ReadThread's lifespan never exceeds StreamIn's lifespan.
     44     ReadThread(std::atomic<bool>* stop, audio_stream_in_t* stream, StreamIn::CommandMQ* commandMQ,
     45                StreamIn::DataMQ* dataMQ, StreamIn::StatusMQ* statusMQ, EventFlag* efGroup)
     46         : Thread(false /*canCallJava*/),
     47           mStop(stop),
     48           mStream(stream),
     49           mCommandMQ(commandMQ),
     50           mDataMQ(dataMQ),
     51           mStatusMQ(statusMQ),
     52           mEfGroup(efGroup),
     53           mBuffer(nullptr) {}
     54     bool init() {
     55         mBuffer.reset(new (std::nothrow) uint8_t[mDataMQ->getQuantumCount()]);
     56         return mBuffer != nullptr;
     57     }
     58     virtual ~ReadThread() {}
     59 
     60    private:
     61     std::atomic<bool>* mStop;
     62     audio_stream_in_t* mStream;
     63     StreamIn::CommandMQ* mCommandMQ;
     64     StreamIn::DataMQ* mDataMQ;
     65     StreamIn::StatusMQ* mStatusMQ;
     66     EventFlag* mEfGroup;
     67     std::unique_ptr<uint8_t[]> mBuffer;
     68     IStreamIn::ReadParameters mParameters;
     69     IStreamIn::ReadStatus mStatus;
     70 
     71     bool threadLoop() override;
     72 
     73     void doGetCapturePosition();
     74     void doRead();
     75 };
     76 
     77 void ReadThread::doRead() {
     78     size_t availableToWrite = mDataMQ->availableToWrite();
     79     size_t requestedToRead = mParameters.params.read;
     80     if (requestedToRead > availableToWrite) {
     81         ALOGW(
     82             "truncating read data from %d to %d due to insufficient data queue "
     83             "space",
     84             (int32_t)requestedToRead, (int32_t)availableToWrite);
     85         requestedToRead = availableToWrite;
     86     }
     87     ssize_t readResult = mStream->read(mStream, &mBuffer[0], requestedToRead);
     88     mStatus.retval = Result::OK;
     89     if (readResult >= 0) {
     90         mStatus.reply.read = readResult;
     91         if (!mDataMQ->write(&mBuffer[0], readResult)) {
     92             ALOGW("data message queue write failed");
     93         }
     94     } else {
     95         mStatus.retval = Stream::analyzeStatus("read", readResult);
     96     }
     97 }
     98 
     99 void ReadThread::doGetCapturePosition() {
    100     mStatus.retval = StreamIn::getCapturePositionImpl(
    101         mStream, &mStatus.reply.capturePosition.frames, &mStatus.reply.capturePosition.time);
    102 }
    103 
    104 bool ReadThread::threadLoop() {
    105     // This implementation doesn't return control back to the Thread until it
    106     // decides to stop,
    107     // as the Thread uses mutexes, and this can lead to priority inversion.
    108     while (!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
    109         uint32_t efState = 0;
    110         mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
    111         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
    112             continue;  // Nothing to do.
    113         }
    114         if (!mCommandMQ->read(&mParameters)) {
    115             continue;  // Nothing to do.
    116         }
    117         mStatus.replyTo = mParameters.command;
    118         switch (mParameters.command) {
    119             case IStreamIn::ReadCommand::READ:
    120                 doRead();
    121                 break;
    122             case IStreamIn::ReadCommand::GET_CAPTURE_POSITION:
    123                 doGetCapturePosition();
    124                 break;
    125             default:
    126                 ALOGE("Unknown read thread command code %d", mParameters.command);
    127                 mStatus.retval = Result::NOT_SUPPORTED;
    128                 break;
    129         }
    130         if (!mStatusMQ->write(&mStatus)) {
    131             ALOGW("status message queue write failed");
    132         }
    133         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
    134     }
    135 
    136     return false;
    137 }
    138 
    139 }  // namespace
    140 
    141 StreamIn::StreamIn(const sp<Device>& device, audio_stream_in_t* stream)
    142     : mIsClosed(false),
    143       mDevice(device),
    144       mStream(stream),
    145       mStreamCommon(new Stream(&stream->common)),
    146       mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
    147       mEfGroup(nullptr),
    148       mStopReadThread(false) {}
    149 
    150 StreamIn::~StreamIn() {
    151     ATRACE_CALL();
    152     close();
    153     if (mReadThread.get()) {
    154         ATRACE_NAME("mReadThread->join");
    155         status_t status = mReadThread->join();
    156         ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
    157     }
    158     if (mEfGroup) {
    159         status_t status = EventFlag::deleteEventFlag(&mEfGroup);
    160         ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
    161     }
    162     mDevice->closeInputStream(mStream);
    163     mStream = nullptr;
    164 }
    165 
    166 // Methods from ::android::hardware::audio::CPP_VERSION::IStream follow.
    167 Return<uint64_t> StreamIn::getFrameSize() {
    168     return audio_stream_in_frame_size(mStream);
    169 }
    170 
    171 Return<uint64_t> StreamIn::getFrameCount() {
    172     return mStreamCommon->getFrameCount();
    173 }
    174 
    175 Return<uint64_t> StreamIn::getBufferSize() {
    176     return mStreamCommon->getBufferSize();
    177 }
    178 
    179 Return<uint32_t> StreamIn::getSampleRate() {
    180     return mStreamCommon->getSampleRate();
    181 }
    182 
    183 #if MAJOR_VERSION == 2
    184 Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb) {
    185     return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
    186 }
    187 Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb) {
    188     return mStreamCommon->getSupportedSampleRates(_hidl_cb);
    189 }
    190 #endif
    191 
    192 Return<void> StreamIn::getSupportedChannelMasks(AudioFormat format,
    193                                                 getSupportedChannelMasks_cb _hidl_cb) {
    194     return mStreamCommon->getSupportedChannelMasks(format, _hidl_cb);
    195 }
    196 Return<void> StreamIn::getSupportedSampleRates(AudioFormat format,
    197                                                getSupportedSampleRates_cb _hidl_cb) {
    198     return mStreamCommon->getSupportedSampleRates(format, _hidl_cb);
    199 }
    200 
    201 Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz) {
    202     return mStreamCommon->setSampleRate(sampleRateHz);
    203 }
    204 
    205 Return<AudioChannelBitfield> StreamIn::getChannelMask() {
    206     return mStreamCommon->getChannelMask();
    207 }
    208 
    209 Return<Result> StreamIn::setChannelMask(AudioChannelBitfield mask) {
    210     return mStreamCommon->setChannelMask(mask);
    211 }
    212 
    213 Return<AudioFormat> StreamIn::getFormat() {
    214     return mStreamCommon->getFormat();
    215 }
    216 
    217 Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb) {
    218     return mStreamCommon->getSupportedFormats(_hidl_cb);
    219 }
    220 
    221 Return<Result> StreamIn::setFormat(AudioFormat format) {
    222     return mStreamCommon->setFormat(format);
    223 }
    224 
    225 Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb) {
    226     return mStreamCommon->getAudioProperties(_hidl_cb);
    227 }
    228 
    229 Return<Result> StreamIn::addEffect(uint64_t effectId) {
    230     return mStreamCommon->addEffect(effectId);
    231 }
    232 
    233 Return<Result> StreamIn::removeEffect(uint64_t effectId) {
    234     return mStreamCommon->removeEffect(effectId);
    235 }
    236 
    237 Return<Result> StreamIn::standby() {
    238     return mStreamCommon->standby();
    239 }
    240 
    241 Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync) {
    242     return mStreamCommon->setHwAvSync(hwAvSync);
    243 }
    244 
    245 #if MAJOR_VERSION == 2
    246 Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected) {
    247     return mStreamCommon->setConnectedState(address, connected);
    248 }
    249 
    250 Return<AudioDevice> StreamIn::getDevice() {
    251     return mStreamCommon->getDevice();
    252 }
    253 
    254 Return<Result> StreamIn::setDevice(const DeviceAddress& address) {
    255     return mStreamCommon->setDevice(address);
    256 }
    257 
    258 Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
    259     return mStreamCommon->getParameters(keys, _hidl_cb);
    260 }
    261 
    262 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters) {
    263     return mStreamCommon->setParameters(parameters);
    264 }
    265 
    266 Return<void> StreamIn::debugDump(const hidl_handle& fd) {
    267     return mStreamCommon->debugDump(fd);
    268 }
    269 #elif MAJOR_VERSION >= 4
    270 Return<void> StreamIn::getDevices(getDevices_cb _hidl_cb) {
    271     return mStreamCommon->getDevices(_hidl_cb);
    272 }
    273 
    274 Return<Result> StreamIn::setDevices(const hidl_vec<DeviceAddress>& devices) {
    275     return mStreamCommon->setDevices(devices);
    276 }
    277 Return<void> StreamIn::getParameters(const hidl_vec<ParameterValue>& context,
    278                                      const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
    279     return mStreamCommon->getParameters(context, keys, _hidl_cb);
    280 }
    281 
    282 Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& context,
    283                                        const hidl_vec<ParameterValue>& parameters) {
    284     return mStreamCommon->setParameters(context, parameters);
    285 }
    286 #endif
    287 
    288 Return<Result> StreamIn::start() {
    289     return mStreamMmap->start();
    290 }
    291 
    292 Return<Result> StreamIn::stop() {
    293     return mStreamMmap->stop();
    294 }
    295 
    296 Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
    297     return mStreamMmap->createMmapBuffer(minSizeFrames, audio_stream_in_frame_size(mStream),
    298                                          _hidl_cb);
    299 }
    300 
    301 Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
    302     return mStreamMmap->getMmapPosition(_hidl_cb);
    303 }
    304 
    305 Return<Result> StreamIn::close() {
    306     if (mIsClosed) return Result::INVALID_STATE;
    307     mIsClosed = true;
    308     if (mReadThread.get()) {
    309         mStopReadThread.store(true, std::memory_order_release);
    310     }
    311     if (mEfGroup) {
    312         mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
    313     }
    314     return Result::OK;
    315 }
    316 
    317 // Methods from ::android::hardware::audio::CPP_VERSION::IStreamIn follow.
    318 Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb) {
    319     int halSource;
    320     Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
    321     AudioSource source(AudioSource::DEFAULT);
    322     if (retval == Result::OK) {
    323         source = AudioSource(halSource);
    324     }
    325     _hidl_cb(retval, source);
    326     return Void();
    327 }
    328 
    329 Return<Result> StreamIn::setGain(float gain) {
    330     if (!isGainNormalized(gain)) {
    331         ALOGW("Can not set a stream input gain (%f) outside [0,1]", gain);
    332         return Result::INVALID_ARGUMENTS;
    333     }
    334     return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
    335 }
    336 
    337 Return<void> StreamIn::prepareForReading(uint32_t frameSize, uint32_t framesCount,
    338                                          prepareForReading_cb _hidl_cb) {
    339     status_t status;
    340     ThreadInfo threadInfo = {0, 0};
    341 
    342     // Wrap the _hidl_cb to return an error
    343     auto sendError = [&threadInfo, &_hidl_cb](Result result) {
    344         _hidl_cb(result, CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(),
    345                  threadInfo);
    346     };
    347 
    348     // Create message queues.
    349     if (mDataMQ) {
    350         ALOGE("the client attempts to call prepareForReading twice");
    351         sendError(Result::INVALID_STATE);
    352         return Void();
    353     }
    354     std::unique_ptr<CommandMQ> tempCommandMQ(new CommandMQ(1));
    355 
    356     // Check frameSize and framesCount
    357     if (frameSize == 0 || framesCount == 0) {
    358         ALOGE("Null frameSize (%u) or framesCount (%u)", frameSize, framesCount);
    359         sendError(Result::INVALID_ARGUMENTS);
    360         return Void();
    361     }
    362 
    363     if (frameSize > Stream::MAX_BUFFER_SIZE / framesCount) {
    364         ALOGE("Buffer too big: %u*%u bytes > MAX_BUFFER_SIZE (%u)", frameSize, framesCount,
    365               Stream::MAX_BUFFER_SIZE);
    366         sendError(Result::INVALID_ARGUMENTS);
    367         return Void();
    368     }
    369     std::unique_ptr<DataMQ> tempDataMQ(new DataMQ(frameSize * framesCount, true /* EventFlag */));
    370 
    371     std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
    372     if (!tempCommandMQ->isValid() || !tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
    373         ALOGE_IF(!tempCommandMQ->isValid(), "command MQ is invalid");
    374         ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
    375         ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
    376         sendError(Result::INVALID_ARGUMENTS);
    377         return Void();
    378     }
    379     EventFlag* tempRawEfGroup{};
    380     status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &tempRawEfGroup);
    381     std::unique_ptr<EventFlag, void (*)(EventFlag*)> tempElfGroup(
    382         tempRawEfGroup, [](auto* ef) { EventFlag::deleteEventFlag(&ef); });
    383     if (status != OK || !tempElfGroup) {
    384         ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
    385         sendError(Result::INVALID_ARGUMENTS);
    386         return Void();
    387     }
    388 
    389     // Create and launch the thread.
    390     auto tempReadThread =
    391         std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(),
    392                                      tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
    393     if (!tempReadThread->init()) {
    394         ALOGW("failed to start reader thread: %s", strerror(-status));
    395         sendError(Result::INVALID_ARGUMENTS);
    396         return Void();
    397     }
    398     status = tempReadThread->run("reader", PRIORITY_URGENT_AUDIO);
    399     if (status != OK) {
    400         ALOGW("failed to start reader thread: %s", strerror(-status));
    401         sendError(Result::INVALID_ARGUMENTS);
    402         return Void();
    403     }
    404 
    405     mCommandMQ = std::move(tempCommandMQ);
    406     mDataMQ = std::move(tempDataMQ);
    407     mStatusMQ = std::move(tempStatusMQ);
    408     mReadThread = tempReadThread.release();
    409     mEfGroup = tempElfGroup.release();
    410     threadInfo.pid = getpid();
    411     threadInfo.tid = mReadThread->getTid();
    412     _hidl_cb(Result::OK, *mCommandMQ->getDesc(), *mDataMQ->getDesc(), *mStatusMQ->getDesc(),
    413              threadInfo);
    414     return Void();
    415 }
    416 
    417 Return<uint32_t> StreamIn::getInputFramesLost() {
    418     return mStream->get_input_frames_lost(mStream);
    419 }
    420 
    421 // static
    422 Result StreamIn::getCapturePositionImpl(audio_stream_in_t* stream, uint64_t* frames,
    423                                         uint64_t* time) {
    424     // HAL may have a stub function, always returning ENOSYS, don't
    425     // spam the log in this case.
    426     static const std::vector<int> ignoredErrors{ENOSYS};
    427     Result retval(Result::NOT_SUPPORTED);
    428     if (stream->get_capture_position == NULL) return retval;
    429     int64_t halFrames, halTime;
    430     retval = Stream::analyzeStatus("get_capture_position",
    431                                    stream->get_capture_position(stream, &halFrames, &halTime),
    432                                    ignoredErrors);
    433     if (retval == Result::OK) {
    434         *frames = halFrames;
    435         *time = halTime;
    436     }
    437     return retval;
    438 };
    439 
    440 Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb) {
    441     uint64_t frames = 0, time = 0;
    442     Result retval = getCapturePositionImpl(mStream, &frames, &time);
    443     _hidl_cb(retval, frames, time);
    444     return Void();
    445 }
    446 
    447 Return<void> StreamIn::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
    448     return mStreamCommon->debug(fd, options);
    449 }
    450 
    451 #if MAJOR_VERSION >= 4
    452 Return<void> StreamIn::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
    453     if (mStream->update_sink_metadata == nullptr) {
    454         return Void();  // not supported by the HAL
    455     }
    456     std::vector<record_track_metadata> halTracks;
    457     halTracks.reserve(sinkMetadata.tracks.size());
    458     for (auto& metadata : sinkMetadata.tracks) {
    459         record_track_metadata halTrackMetadata = {
    460             .source = static_cast<audio_source_t>(metadata.source), .gain = metadata.gain};
    461 #if MAJOR_VERSION >= 5
    462         if (metadata.destination.getDiscriminator() ==
    463             RecordTrackMetadata::Destination::hidl_discriminator::device) {
    464             halTrackMetadata.dest_device =
    465                 static_cast<audio_devices_t>(metadata.destination.device().device);
    466             strncpy(halTrackMetadata.dest_device_address,
    467                     deviceAddressToHal(metadata.destination.device()).c_str(),
    468                     AUDIO_DEVICE_MAX_ADDRESS_LEN);
    469         }
    470 #endif
    471         halTracks.push_back(halTrackMetadata);
    472     }
    473     const sink_metadata_t halMetadata = {
    474         .track_count = halTracks.size(),
    475         .tracks = halTracks.data(),
    476     };
    477     mStream->update_sink_metadata(mStream, &halMetadata);
    478     return Void();
    479 }
    480 
    481 Return<void> StreamIn::getActiveMicrophones(getActiveMicrophones_cb _hidl_cb) {
    482     Result retval = Result::NOT_SUPPORTED;
    483     size_t actual_mics = AUDIO_MICROPHONE_MAX_COUNT;
    484     audio_microphone_characteristic_t mic_array[AUDIO_MICROPHONE_MAX_COUNT];
    485 
    486     hidl_vec<MicrophoneInfo> microphones;
    487     if (mStream->get_active_microphones != NULL &&
    488         mStream->get_active_microphones(mStream, &mic_array[0], &actual_mics) == 0) {
    489         microphones.resize(actual_mics);
    490         for (size_t i = 0; i < actual_mics; ++i) {
    491             halToMicrophoneCharacteristics(&microphones[i], mic_array[i]);
    492         }
    493         retval = Result::OK;
    494     }
    495 
    496     _hidl_cb(retval, microphones);
    497     return Void();
    498 }
    499 #endif
    500 
    501 #if MAJOR_VERSION >= 5
    502 Return<Result> StreamIn::setMicrophoneDirection(MicrophoneDirection direction) {
    503     if (mStream->set_microphone_direction == nullptr) {
    504         return Result::NOT_SUPPORTED;
    505     }
    506     if (!common::utils::isValidHidlEnum(direction)) {
    507         ALOGE("%s: Invalid direction %d", __func__, direction);
    508         return Result::INVALID_ARGUMENTS;
    509     }
    510     return Stream::analyzeStatus(
    511             "set_microphone_direction",
    512             mStream->set_microphone_direction(
    513                     mStream, static_cast<audio_microphone_direction_t>(direction)));
    514 }
    515 
    516 Return<Result> StreamIn::setMicrophoneFieldDimension(float zoom) {
    517     if (mStream->set_microphone_field_dimension == nullptr) {
    518         return Result::NOT_SUPPORTED;
    519     }
    520     if (std::isnan(zoom) || zoom < -1 || zoom > 1) {
    521         ALOGE("%s: Invalid zoom %f", __func__, zoom);
    522         return Result::INVALID_ARGUMENTS;
    523     }
    524     return Stream::analyzeStatus("set_microphone_field_dimension",
    525                                  mStream->set_microphone_field_dimension(mStream, zoom));
    526 }
    527 
    528 #endif
    529 
    530 }  // namespace implementation
    531 }  // namespace CPP_VERSION
    532 }  // namespace audio
    533 }  // namespace hardware
    534 }  // namespace android
    535