Home | History | Annotate | Download | only in libaudiohal
      1 /*
      2  * Copyright (C) 2016 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 "StreamHalHidl"
     18 //#define LOG_NDEBUG 0
     19 
     20 #include <android/hardware/audio/2.0/IStreamOutCallback.h>
     21 #include <hwbinder/IPCThreadState.h>
     22 #include <mediautils/SchedulingPolicyService.h>
     23 #include <utils/Log.h>
     24 
     25 #include "DeviceHalHidl.h"
     26 #include "EffectHalHidl.h"
     27 #include "StreamHalHidl.h"
     28 
     29 using ::android::hardware::audio::common::V2_0::AudioChannelMask;
     30 using ::android::hardware::audio::common::V2_0::AudioFormat;
     31 using ::android::hardware::audio::common::V2_0::ThreadInfo;
     32 using ::android::hardware::audio::V2_0::AudioDrain;
     33 using ::android::hardware::audio::V2_0::IStreamOutCallback;
     34 using ::android::hardware::audio::V2_0::MessageQueueFlagBits;
     35 using ::android::hardware::audio::V2_0::MmapBufferInfo;
     36 using ::android::hardware::audio::V2_0::MmapPosition;
     37 using ::android::hardware::audio::V2_0::ParameterValue;
     38 using ::android::hardware::audio::V2_0::Result;
     39 using ::android::hardware::audio::V2_0::TimeSpec;
     40 using ::android::hardware::MQDescriptorSync;
     41 using ::android::hardware::Return;
     42 using ::android::hardware::Void;
     43 using ReadCommand = ::android::hardware::audio::V2_0::IStreamIn::ReadCommand;
     44 
     45 namespace android {
     46 
     47 StreamHalHidl::StreamHalHidl(IStream *stream)
     48         : ConversionHelperHidl("Stream"),
     49           mStream(stream),
     50           mHalThreadPriority(HAL_THREAD_PRIORITY_DEFAULT),
     51           mCachedBufferSize(0){
     52 
     53     // Instrument audio signal power logging.
     54     // Note: This assumes channel mask, format, and sample rate do not change after creation.
     55     if (mStream != nullptr && mStreamPowerLog.isUserDebugOrEngBuild()) {
     56         // Obtain audio properties (see StreamHalHidl::getAudioProperties() below).
     57         Return<void> ret = mStream->getAudioProperties(
     58                 [&](uint32_t sr, AudioChannelMask m, AudioFormat f) {
     59                 mStreamPowerLog.init(sr,
     60                         static_cast<audio_channel_mask_t>(m),
     61                         static_cast<audio_format_t>(f));
     62             });
     63     }
     64 }
     65 
     66 StreamHalHidl::~StreamHalHidl() {
     67     mStream = nullptr;
     68 }
     69 
     70 status_t StreamHalHidl::getSampleRate(uint32_t *rate) {
     71     if (!mStream) return NO_INIT;
     72     return processReturn("getSampleRate", mStream->getSampleRate(), rate);
     73 }
     74 
     75 status_t StreamHalHidl::getBufferSize(size_t *size) {
     76     if (!mStream) return NO_INIT;
     77     status_t status = processReturn("getBufferSize", mStream->getBufferSize(), size);
     78     if (status == OK) {
     79         mCachedBufferSize = *size;
     80     }
     81     return status;
     82 }
     83 
     84 status_t StreamHalHidl::getChannelMask(audio_channel_mask_t *mask) {
     85     if (!mStream) return NO_INIT;
     86     return processReturn("getChannelMask", mStream->getChannelMask(), mask);
     87 }
     88 
     89 status_t StreamHalHidl::getFormat(audio_format_t *format) {
     90     if (!mStream) return NO_INIT;
     91     return processReturn("getFormat", mStream->getFormat(), format);
     92 }
     93 
     94 status_t StreamHalHidl::getAudioProperties(
     95         uint32_t *sampleRate, audio_channel_mask_t *mask, audio_format_t *format) {
     96     if (!mStream) return NO_INIT;
     97     Return<void> ret = mStream->getAudioProperties(
     98             [&](uint32_t sr, AudioChannelMask m, AudioFormat f) {
     99                 *sampleRate = sr;
    100                 *mask = static_cast<audio_channel_mask_t>(m);
    101                 *format = static_cast<audio_format_t>(f);
    102             });
    103     return processReturn("getAudioProperties", ret);
    104 }
    105 
    106 status_t StreamHalHidl::setParameters(const String8& kvPairs) {
    107     if (!mStream) return NO_INIT;
    108     hidl_vec<ParameterValue> hidlParams;
    109     status_t status = parametersFromHal(kvPairs, &hidlParams);
    110     if (status != OK) return status;
    111     return processReturn("setParameters", mStream->setParameters(hidlParams));
    112 }
    113 
    114 status_t StreamHalHidl::getParameters(const String8& keys, String8 *values) {
    115     values->clear();
    116     if (!mStream) return NO_INIT;
    117     hidl_vec<hidl_string> hidlKeys;
    118     status_t status = keysFromHal(keys, &hidlKeys);
    119     if (status != OK) return status;
    120     Result retval;
    121     Return<void> ret = mStream->getParameters(
    122             hidlKeys,
    123             [&](Result r, const hidl_vec<ParameterValue>& parameters) {
    124                 retval = r;
    125                 if (retval == Result::OK) {
    126                     parametersToHal(parameters, values);
    127                 }
    128             });
    129     return processReturn("getParameters", ret, retval);
    130 }
    131 
    132 status_t StreamHalHidl::addEffect(sp<EffectHalInterface> effect) {
    133     if (!mStream) return NO_INIT;
    134     return processReturn("addEffect", mStream->addEffect(
    135                     static_cast<EffectHalHidl*>(effect.get())->effectId()));
    136 }
    137 
    138 status_t StreamHalHidl::removeEffect(sp<EffectHalInterface> effect) {
    139     if (!mStream) return NO_INIT;
    140     return processReturn("removeEffect", mStream->removeEffect(
    141                     static_cast<EffectHalHidl*>(effect.get())->effectId()));
    142 }
    143 
    144 status_t StreamHalHidl::standby() {
    145     if (!mStream) return NO_INIT;
    146     return processReturn("standby", mStream->standby());
    147 }
    148 
    149 status_t StreamHalHidl::dump(int fd) {
    150     if (!mStream) return NO_INIT;
    151     native_handle_t* hidlHandle = native_handle_create(1, 0);
    152     hidlHandle->data[0] = fd;
    153     Return<void> ret = mStream->debugDump(hidlHandle);
    154     native_handle_delete(hidlHandle);
    155     mStreamPowerLog.dump(fd);
    156     return processReturn("dump", ret);
    157 }
    158 
    159 status_t StreamHalHidl::start() {
    160     if (!mStream) return NO_INIT;
    161     return processReturn("start", mStream->start());
    162 }
    163 
    164 status_t StreamHalHidl::stop() {
    165     if (!mStream) return NO_INIT;
    166     return processReturn("stop", mStream->stop());
    167 }
    168 
    169 status_t StreamHalHidl::createMmapBuffer(int32_t minSizeFrames,
    170                                   struct audio_mmap_buffer_info *info) {
    171     Result retval;
    172     Return<void> ret = mStream->createMmapBuffer(
    173             minSizeFrames,
    174             [&](Result r, const MmapBufferInfo& hidlInfo) {
    175                 retval = r;
    176                 if (retval == Result::OK) {
    177                     const native_handle *handle = hidlInfo.sharedMemory.handle();
    178                     if (handle->numFds > 0) {
    179                         info->shared_memory_fd = handle->data[0];
    180                         info->buffer_size_frames = hidlInfo.bufferSizeFrames;
    181                         info->burst_size_frames = hidlInfo.burstSizeFrames;
    182                         // info->shared_memory_address is not needed in HIDL context
    183                         info->shared_memory_address = NULL;
    184                     } else {
    185                         retval = Result::NOT_INITIALIZED;
    186                     }
    187                 }
    188             });
    189     return processReturn("createMmapBuffer", ret, retval);
    190 }
    191 
    192 status_t StreamHalHidl::getMmapPosition(struct audio_mmap_position *position) {
    193     Result retval;
    194     Return<void> ret = mStream->getMmapPosition(
    195             [&](Result r, const MmapPosition& hidlPosition) {
    196                 retval = r;
    197                 if (retval == Result::OK) {
    198                     position->time_nanoseconds = hidlPosition.timeNanoseconds;
    199                     position->position_frames = hidlPosition.positionFrames;
    200                 }
    201             });
    202     return processReturn("getMmapPosition", ret, retval);
    203 }
    204 
    205 status_t StreamHalHidl::setHalThreadPriority(int priority) {
    206     mHalThreadPriority = priority;
    207     return OK;
    208 }
    209 
    210 status_t StreamHalHidl::getCachedBufferSize(size_t *size) {
    211     if (mCachedBufferSize != 0) {
    212         *size = mCachedBufferSize;
    213         return OK;
    214     }
    215     return getBufferSize(size);
    216 }
    217 
    218 bool StreamHalHidl::requestHalThreadPriority(pid_t threadPid, pid_t threadId) {
    219     if (mHalThreadPriority == HAL_THREAD_PRIORITY_DEFAULT) {
    220         return true;
    221     }
    222     int err = requestPriority(
    223             threadPid, threadId,
    224             mHalThreadPriority, false /*isForApp*/, true /*asynchronous*/);
    225     ALOGE_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
    226             mHalThreadPriority, threadPid, threadId, err);
    227     // Audio will still work, but latency will be higher and sometimes unacceptable.
    228     return err == 0;
    229 }
    230 
    231 namespace {
    232 
    233 /* Notes on callback ownership.
    234 
    235 This is how (Hw)Binder ownership model looks like. The server implementation
    236 is owned by Binder framework (via sp<>). Proxies are owned by clients.
    237 When the last proxy disappears, Binder framework releases the server impl.
    238 
    239 Thus, it is not needed to keep any references to StreamOutCallback (this is
    240 the server impl) -- it will live as long as HAL server holds a strong ref to
    241 IStreamOutCallback proxy. We clear that reference by calling 'clearCallback'
    242 from the destructor of StreamOutHalHidl.
    243 
    244 The callback only keeps a weak reference to the stream. The stream is owned
    245 by AudioFlinger.
    246 
    247 */
    248 
    249 struct StreamOutCallback : public IStreamOutCallback {
    250     StreamOutCallback(const wp<StreamOutHalHidl>& stream) : mStream(stream) {}
    251 
    252     // IStreamOutCallback implementation
    253     Return<void> onWriteReady()  override {
    254         sp<StreamOutHalHidl> stream = mStream.promote();
    255         if (stream != 0) {
    256             stream->onWriteReady();
    257         }
    258         return Void();
    259     }
    260 
    261     Return<void> onDrainReady()  override {
    262         sp<StreamOutHalHidl> stream = mStream.promote();
    263         if (stream != 0) {
    264             stream->onDrainReady();
    265         }
    266         return Void();
    267     }
    268 
    269     Return<void> onError()  override {
    270         sp<StreamOutHalHidl> stream = mStream.promote();
    271         if (stream != 0) {
    272             stream->onError();
    273         }
    274         return Void();
    275     }
    276 
    277   private:
    278     wp<StreamOutHalHidl> mStream;
    279 };
    280 
    281 }  // namespace
    282 
    283 StreamOutHalHidl::StreamOutHalHidl(const sp<IStreamOut>& stream)
    284         : StreamHalHidl(stream.get()), mStream(stream), mWriterClient(0), mEfGroup(nullptr) {
    285 }
    286 
    287 StreamOutHalHidl::~StreamOutHalHidl() {
    288     if (mStream != 0) {
    289         if (mCallback.unsafe_get()) {
    290             processReturn("clearCallback", mStream->clearCallback());
    291         }
    292         processReturn("close", mStream->close());
    293         mStream.clear();
    294     }
    295     mCallback.clear();
    296     hardware::IPCThreadState::self()->flushCommands();
    297     if (mEfGroup) {
    298         EventFlag::deleteEventFlag(&mEfGroup);
    299     }
    300 }
    301 
    302 status_t StreamOutHalHidl::getFrameSize(size_t *size) {
    303     if (mStream == 0) return NO_INIT;
    304     return processReturn("getFrameSize", mStream->getFrameSize(), size);
    305 }
    306 
    307 status_t StreamOutHalHidl::getLatency(uint32_t *latency) {
    308     if (mStream == 0) return NO_INIT;
    309     if (mWriterClient == gettid() && mCommandMQ) {
    310         return callWriterThread(
    311                 WriteCommand::GET_LATENCY, "getLatency", nullptr, 0,
    312                 [&](const WriteStatus& writeStatus) {
    313                     *latency = writeStatus.reply.latencyMs;
    314                 });
    315     } else {
    316         return processReturn("getLatency", mStream->getLatency(), latency);
    317     }
    318 }
    319 
    320 status_t StreamOutHalHidl::setVolume(float left, float right) {
    321     if (mStream == 0) return NO_INIT;
    322     return processReturn("setVolume", mStream->setVolume(left, right));
    323 }
    324 
    325 status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
    326     if (mStream == 0) return NO_INIT;
    327     *written = 0;
    328 
    329     if (bytes == 0 && !mDataMQ) {
    330         // Can't determine the size for the MQ buffer. Wait for a non-empty write request.
    331         ALOGW_IF(mCallback.unsafe_get(), "First call to async write with 0 bytes");
    332         return OK;
    333     }
    334 
    335     status_t status;
    336     if (!mDataMQ) {
    337         // In case if playback starts close to the end of a compressed track, the bytes
    338         // that need to be written is less than the actual buffer size. Need to use
    339         // full buffer size for the MQ since otherwise after seeking back to the middle
    340         // data will be truncated.
    341         size_t bufferSize;
    342         if ((status = getCachedBufferSize(&bufferSize)) != OK) {
    343             return status;
    344         }
    345         if (bytes > bufferSize) bufferSize = bytes;
    346         if ((status = prepareForWriting(bufferSize)) != OK) {
    347             return status;
    348         }
    349     }
    350 
    351     status = callWriterThread(
    352             WriteCommand::WRITE, "write", static_cast<const uint8_t*>(buffer), bytes,
    353             [&] (const WriteStatus& writeStatus) {
    354                 *written = writeStatus.reply.written;
    355                 // Diagnostics of the cause of b/35813113.
    356                 ALOGE_IF(*written > bytes,
    357                         "hal reports more bytes written than asked for: %lld > %lld",
    358                         (long long)*written, (long long)bytes);
    359             });
    360     mStreamPowerLog.log(buffer, *written);
    361     return status;
    362 }
    363 
    364 status_t StreamOutHalHidl::callWriterThread(
    365         WriteCommand cmd, const char* cmdName,
    366         const uint8_t* data, size_t dataSize, StreamOutHalHidl::WriterCallback callback) {
    367     if (!mCommandMQ->write(&cmd)) {
    368         ALOGE("command message queue write failed for \"%s\"", cmdName);
    369         return -EAGAIN;
    370     }
    371     if (data != nullptr) {
    372         size_t availableToWrite = mDataMQ->availableToWrite();
    373         if (dataSize > availableToWrite) {
    374             ALOGW("truncating write data from %lld to %lld due to insufficient data queue space",
    375                     (long long)dataSize, (long long)availableToWrite);
    376             dataSize = availableToWrite;
    377         }
    378         if (!mDataMQ->write(data, dataSize)) {
    379             ALOGE("data message queue write failed for \"%s\"", cmdName);
    380         }
    381     }
    382     mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
    383 
    384     // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
    385     uint32_t efState = 0;
    386 retry:
    387     status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
    388     if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL)) {
    389         WriteStatus writeStatus;
    390         writeStatus.retval = Result::NOT_INITIALIZED;
    391         if (!mStatusMQ->read(&writeStatus)) {
    392             ALOGE("status message read failed for \"%s\"", cmdName);
    393         }
    394         if (writeStatus.retval == Result::OK) {
    395             ret = OK;
    396             callback(writeStatus);
    397         } else {
    398             ret = processReturn(cmdName, writeStatus.retval);
    399         }
    400         return ret;
    401     }
    402     if (ret == -EAGAIN || ret == -EINTR) {
    403         // Spurious wakeup. This normally retries no more than once.
    404         goto retry;
    405     }
    406     return ret;
    407 }
    408 
    409 status_t StreamOutHalHidl::prepareForWriting(size_t bufferSize) {
    410     std::unique_ptr<CommandMQ> tempCommandMQ;
    411     std::unique_ptr<DataMQ> tempDataMQ;
    412     std::unique_ptr<StatusMQ> tempStatusMQ;
    413     Result retval;
    414     pid_t halThreadPid, halThreadTid;
    415     Return<void> ret = mStream->prepareForWriting(
    416             1, bufferSize,
    417             [&](Result r,
    418                     const CommandMQ::Descriptor& commandMQ,
    419                     const DataMQ::Descriptor& dataMQ,
    420                     const StatusMQ::Descriptor& statusMQ,
    421                     const ThreadInfo& halThreadInfo) {
    422                 retval = r;
    423                 if (retval == Result::OK) {
    424                     tempCommandMQ.reset(new CommandMQ(commandMQ));
    425                     tempDataMQ.reset(new DataMQ(dataMQ));
    426                     tempStatusMQ.reset(new StatusMQ(statusMQ));
    427                     if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
    428                         EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
    429                     }
    430                     halThreadPid = halThreadInfo.pid;
    431                     halThreadTid = halThreadInfo.tid;
    432                 }
    433             });
    434     if (!ret.isOk() || retval != Result::OK) {
    435         return processReturn("prepareForWriting", ret, retval);
    436     }
    437     if (!tempCommandMQ || !tempCommandMQ->isValid() ||
    438             !tempDataMQ || !tempDataMQ->isValid() ||
    439             !tempStatusMQ || !tempStatusMQ->isValid() ||
    440             !mEfGroup) {
    441         ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
    442         ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
    443                 "Command message queue for writing is invalid");
    444         ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for writing");
    445         ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for writing is invalid");
    446         ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for writing");
    447         ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
    448                 "Status message queue for writing is invalid");
    449         ALOGE_IF(!mEfGroup, "Event flag creation for writing failed");
    450         return NO_INIT;
    451     }
    452     requestHalThreadPriority(halThreadPid, halThreadTid);
    453 
    454     mCommandMQ = std::move(tempCommandMQ);
    455     mDataMQ = std::move(tempDataMQ);
    456     mStatusMQ = std::move(tempStatusMQ);
    457     mWriterClient = gettid();
    458     return OK;
    459 }
    460 
    461 status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
    462     if (mStream == 0) return NO_INIT;
    463     Result retval;
    464     Return<void> ret = mStream->getRenderPosition(
    465             [&](Result r, uint32_t d) {
    466                 retval = r;
    467                 if (retval == Result::OK) {
    468                     *dspFrames = d;
    469                 }
    470             });
    471     return processReturn("getRenderPosition", ret, retval);
    472 }
    473 
    474 status_t StreamOutHalHidl::getNextWriteTimestamp(int64_t *timestamp) {
    475     if (mStream == 0) return NO_INIT;
    476     Result retval;
    477     Return<void> ret = mStream->getNextWriteTimestamp(
    478             [&](Result r, int64_t t) {
    479                 retval = r;
    480                 if (retval == Result::OK) {
    481                     *timestamp = t;
    482                 }
    483             });
    484     return processReturn("getRenderPosition", ret, retval);
    485 }
    486 
    487 status_t StreamOutHalHidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
    488     if (mStream == 0) return NO_INIT;
    489     status_t status = processReturn(
    490             "setCallback", mStream->setCallback(new StreamOutCallback(this)));
    491     if (status == OK) {
    492         mCallback = callback;
    493     }
    494     return status;
    495 }
    496 
    497 status_t StreamOutHalHidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
    498     if (mStream == 0) return NO_INIT;
    499     Return<void> ret = mStream->supportsPauseAndResume(
    500             [&](bool p, bool r) {
    501                 *supportsPause = p;
    502                 *supportsResume = r;
    503             });
    504     return processReturn("supportsPauseAndResume", ret);
    505 }
    506 
    507 status_t StreamOutHalHidl::pause() {
    508     if (mStream == 0) return NO_INIT;
    509     return processReturn("pause", mStream->pause());
    510 }
    511 
    512 status_t StreamOutHalHidl::resume() {
    513     if (mStream == 0) return NO_INIT;
    514     return processReturn("pause", mStream->resume());
    515 }
    516 
    517 status_t StreamOutHalHidl::supportsDrain(bool *supportsDrain) {
    518     if (mStream == 0) return NO_INIT;
    519     return processReturn("supportsDrain", mStream->supportsDrain(), supportsDrain);
    520 }
    521 
    522 status_t StreamOutHalHidl::drain(bool earlyNotify) {
    523     if (mStream == 0) return NO_INIT;
    524     return processReturn(
    525             "drain", mStream->drain(earlyNotify ? AudioDrain::EARLY_NOTIFY : AudioDrain::ALL));
    526 }
    527 
    528 status_t StreamOutHalHidl::flush() {
    529     if (mStream == 0) return NO_INIT;
    530     return processReturn("pause", mStream->flush());
    531 }
    532 
    533 status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
    534     if (mStream == 0) return NO_INIT;
    535     if (mWriterClient == gettid() && mCommandMQ) {
    536         return callWriterThread(
    537                 WriteCommand::GET_PRESENTATION_POSITION, "getPresentationPosition", nullptr, 0,
    538                 [&](const WriteStatus& writeStatus) {
    539                     *frames = writeStatus.reply.presentationPosition.frames;
    540                     timestamp->tv_sec = writeStatus.reply.presentationPosition.timeStamp.tvSec;
    541                     timestamp->tv_nsec = writeStatus.reply.presentationPosition.timeStamp.tvNSec;
    542                 });
    543     } else {
    544         Result retval;
    545         Return<void> ret = mStream->getPresentationPosition(
    546                 [&](Result r, uint64_t hidlFrames, const TimeSpec& hidlTimeStamp) {
    547                     retval = r;
    548                     if (retval == Result::OK) {
    549                         *frames = hidlFrames;
    550                         timestamp->tv_sec = hidlTimeStamp.tvSec;
    551                         timestamp->tv_nsec = hidlTimeStamp.tvNSec;
    552                     }
    553                 });
    554         return processReturn("getPresentationPosition", ret, retval);
    555     }
    556 }
    557 
    558 void StreamOutHalHidl::onWriteReady() {
    559     sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
    560     if (callback == 0) return;
    561     ALOGV("asyncCallback onWriteReady");
    562     callback->onWriteReady();
    563 }
    564 
    565 void StreamOutHalHidl::onDrainReady() {
    566     sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
    567     if (callback == 0) return;
    568     ALOGV("asyncCallback onDrainReady");
    569     callback->onDrainReady();
    570 }
    571 
    572 void StreamOutHalHidl::onError() {
    573     sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
    574     if (callback == 0) return;
    575     ALOGV("asyncCallback onError");
    576     callback->onError();
    577 }
    578 
    579 
    580 StreamInHalHidl::StreamInHalHidl(const sp<IStreamIn>& stream)
    581         : StreamHalHidl(stream.get()), mStream(stream), mReaderClient(0), mEfGroup(nullptr) {
    582 }
    583 
    584 StreamInHalHidl::~StreamInHalHidl() {
    585     if (mStream != 0) {
    586         processReturn("close", mStream->close());
    587         mStream.clear();
    588         hardware::IPCThreadState::self()->flushCommands();
    589     }
    590     if (mEfGroup) {
    591         EventFlag::deleteEventFlag(&mEfGroup);
    592     }
    593 }
    594 
    595 status_t StreamInHalHidl::getFrameSize(size_t *size) {
    596     if (mStream == 0) return NO_INIT;
    597     return processReturn("getFrameSize", mStream->getFrameSize(), size);
    598 }
    599 
    600 status_t StreamInHalHidl::setGain(float gain) {
    601     if (mStream == 0) return NO_INIT;
    602     return processReturn("setGain", mStream->setGain(gain));
    603 }
    604 
    605 status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
    606     if (mStream == 0) return NO_INIT;
    607     *read = 0;
    608 
    609     if (bytes == 0 && !mDataMQ) {
    610         // Can't determine the size for the MQ buffer. Wait for a non-empty read request.
    611         return OK;
    612     }
    613 
    614     status_t status;
    615     if (!mDataMQ && (status = prepareForReading(bytes)) != OK) {
    616         return status;
    617     }
    618 
    619     ReadParameters params;
    620     params.command = ReadCommand::READ;
    621     params.params.read = bytes;
    622     status = callReaderThread(params, "read",
    623             [&](const ReadStatus& readStatus) {
    624                 const size_t availToRead = mDataMQ->availableToRead();
    625                 if (!mDataMQ->read(static_cast<uint8_t*>(buffer), std::min(bytes, availToRead))) {
    626                     ALOGE("data message queue read failed for \"read\"");
    627                 }
    628                 ALOGW_IF(availToRead != readStatus.reply.read,
    629                         "HAL read report inconsistent: mq = %d, status = %d",
    630                         (int32_t)availToRead, (int32_t)readStatus.reply.read);
    631                 *read = readStatus.reply.read;
    632             });
    633     mStreamPowerLog.log(buffer, *read);
    634     return status;
    635 }
    636 
    637 status_t StreamInHalHidl::callReaderThread(
    638         const ReadParameters& params, const char* cmdName,
    639         StreamInHalHidl::ReaderCallback callback) {
    640     if (!mCommandMQ->write(&params)) {
    641         ALOGW("command message queue write failed");
    642         return -EAGAIN;
    643     }
    644     mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
    645 
    646     // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
    647     uint32_t efState = 0;
    648 retry:
    649     status_t ret = mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
    650     if (efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY)) {
    651         ReadStatus readStatus;
    652         readStatus.retval = Result::NOT_INITIALIZED;
    653         if (!mStatusMQ->read(&readStatus)) {
    654             ALOGE("status message read failed for \"%s\"", cmdName);
    655         }
    656          if (readStatus.retval == Result::OK) {
    657             ret = OK;
    658             callback(readStatus);
    659         } else {
    660             ret = processReturn(cmdName, readStatus.retval);
    661         }
    662         return ret;
    663     }
    664     if (ret == -EAGAIN || ret == -EINTR) {
    665         // Spurious wakeup. This normally retries no more than once.
    666         goto retry;
    667     }
    668     return ret;
    669 }
    670 
    671 status_t StreamInHalHidl::prepareForReading(size_t bufferSize) {
    672     std::unique_ptr<CommandMQ> tempCommandMQ;
    673     std::unique_ptr<DataMQ> tempDataMQ;
    674     std::unique_ptr<StatusMQ> tempStatusMQ;
    675     Result retval;
    676     pid_t halThreadPid, halThreadTid;
    677     Return<void> ret = mStream->prepareForReading(
    678             1, bufferSize,
    679             [&](Result r,
    680                     const CommandMQ::Descriptor& commandMQ,
    681                     const DataMQ::Descriptor& dataMQ,
    682                     const StatusMQ::Descriptor& statusMQ,
    683                     const ThreadInfo& halThreadInfo) {
    684                 retval = r;
    685                 if (retval == Result::OK) {
    686                     tempCommandMQ.reset(new CommandMQ(commandMQ));
    687                     tempDataMQ.reset(new DataMQ(dataMQ));
    688                     tempStatusMQ.reset(new StatusMQ(statusMQ));
    689                     if (tempDataMQ->isValid() && tempDataMQ->getEventFlagWord()) {
    690                         EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
    691                     }
    692                     halThreadPid = halThreadInfo.pid;
    693                     halThreadTid = halThreadInfo.tid;
    694                 }
    695             });
    696     if (!ret.isOk() || retval != Result::OK) {
    697         return processReturn("prepareForReading", ret, retval);
    698     }
    699     if (!tempCommandMQ || !tempCommandMQ->isValid() ||
    700             !tempDataMQ || !tempDataMQ->isValid() ||
    701             !tempStatusMQ || !tempStatusMQ->isValid() ||
    702             !mEfGroup) {
    703         ALOGE_IF(!tempCommandMQ, "Failed to obtain command message queue for writing");
    704         ALOGE_IF(tempCommandMQ && !tempCommandMQ->isValid(),
    705                 "Command message queue for writing is invalid");
    706         ALOGE_IF(!tempDataMQ, "Failed to obtain data message queue for reading");
    707         ALOGE_IF(tempDataMQ && !tempDataMQ->isValid(), "Data message queue for reading is invalid");
    708         ALOGE_IF(!tempStatusMQ, "Failed to obtain status message queue for reading");
    709         ALOGE_IF(tempStatusMQ && !tempStatusMQ->isValid(),
    710                 "Status message queue for reading is invalid");
    711         ALOGE_IF(!mEfGroup, "Event flag creation for reading failed");
    712         return NO_INIT;
    713     }
    714     requestHalThreadPriority(halThreadPid, halThreadTid);
    715 
    716     mCommandMQ = std::move(tempCommandMQ);
    717     mDataMQ = std::move(tempDataMQ);
    718     mStatusMQ = std::move(tempStatusMQ);
    719     mReaderClient = gettid();
    720     return OK;
    721 }
    722 
    723 status_t StreamInHalHidl::getInputFramesLost(uint32_t *framesLost) {
    724     if (mStream == 0) return NO_INIT;
    725     return processReturn("getInputFramesLost", mStream->getInputFramesLost(), framesLost);
    726 }
    727 
    728 status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
    729     if (mStream == 0) return NO_INIT;
    730     if (mReaderClient == gettid() && mCommandMQ) {
    731         ReadParameters params;
    732         params.command = ReadCommand::GET_CAPTURE_POSITION;
    733         return callReaderThread(params, "getCapturePosition",
    734                 [&](const ReadStatus& readStatus) {
    735                     *frames = readStatus.reply.capturePosition.frames;
    736                     *time = readStatus.reply.capturePosition.time;
    737                 });
    738     } else {
    739         Result retval;
    740         Return<void> ret = mStream->getCapturePosition(
    741                 [&](Result r, uint64_t hidlFrames, uint64_t hidlTime) {
    742                     retval = r;
    743                     if (retval == Result::OK) {
    744                         *frames = hidlFrames;
    745                         *time = hidlTime;
    746                     }
    747                 });
    748         return processReturn("getCapturePosition", ret, retval);
    749     }
    750 }
    751 
    752 } // namespace android
    753