Loading media/libaudiohal/impl/EffectConversionHelperAidl.cpp +21 −10 Original line number Diff line number Diff line Loading @@ -187,16 +187,7 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi IEffect::OpenEffectReturn openReturn; RETURN_STATUS_IF_ERROR( statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn))); if (mIsProxyEffect) { mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ(); mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ(); mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ(); } else { mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ); mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ); mOutputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ); } updateMqs(openReturn); if (status_t status = updateEventFlags(); status != OK) { ALOGV("%s closing at status %d", __func__, status); Loading @@ -213,6 +204,18 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi return *static_cast<int32_t*>(pReplyData) = OK; } void EffectConversionHelperAidl::updateMqs(const IEffect::OpenEffectReturn& ret) { if (mIsProxyEffect) { mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ(); mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ(); mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ(); } else { mStatusQ = std::make_shared<StatusMQ>(ret.statusMQ); mInputQ = std::make_shared<DataMQ>(ret.inputDataMQ); mOutputQ = std::make_shared<DataMQ>(ret.outputDataMQ); } } status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused, const void* pCmdData __unused, uint32_t* replySize, void* pReplyData) { Loading Loading @@ -505,5 +508,13 @@ Descriptor EffectConversionHelperAidl::getDescriptor() const { return desc; } status_t EffectConversionHelperAidl::reopen() { IEffect::OpenEffectReturn openReturn; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->reopen(&openReturn))); updateMqs(openReturn); return OK; } } // namespace effect } // namespace android media/libaudiohal/impl/EffectConversionHelperAidl.h +3 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ class EffectConversionHelperAidl { bool isBypassingOrTunnel() const; ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const; status_t reopen(); protected: const int32_t mSessionId; Loading Loading @@ -108,6 +109,8 @@ class EffectConversionHelperAidl { std::shared_ptr<android::hardware::EventFlag> mEfGroup = nullptr; status_t updateEventFlags(); void updateMqs(const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn& ret); status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize, void* pReplyData); status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize, Loading media/libaudiohal/impl/EffectHalAidl.cpp +21 −9 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ using ::aidl::android::aidl_utils::statusTFromBinderStatus; using ::aidl::android::hardware::audio::effect::Descriptor; using ::aidl::android::hardware::audio::effect::IEffect; using ::aidl::android::hardware::audio::effect::IFactory; using ::aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate; using ::aidl::android::hardware::audio::effect::State; namespace android { Loading Loading @@ -165,26 +166,37 @@ status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ status_t EffectHalAidl::process() { const std::string effectName = mConversion->getDescriptor().common.name; State state = State::INIT; if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() || state != State::PROCESSING) { ALOGI("%s skipping %s process because it's %s", __func__, mConversion->getDescriptor().common.name.c_str(), ALOGI("%s skipping %s process because it's %s", __func__, effectName.c_str(), mConversion->isBypassing() ? "bypassing" : aidl::android::hardware::audio::effect::toString(state).c_str()); return -ENODATA; } // check if the DataMq needs any update, timeout at 1ns to avoid being blocked auto efGroup = mConversion->getEventFlagGroup(); if (!efGroup) { ALOGE("%s invalid efGroup", __func__); return INVALID_OPERATION; } if (uint32_t efState = 0; ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState, 1 /* ns */, true /* retry */)) { ALOGI("%s %s receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str()); mConversion->reopen(); } auto statusQ = mConversion->getStatusMQ(); auto inputQ = mConversion->getInputMQ(); auto outputQ = mConversion->getOutputMQ(); auto efGroup = mConversion->getEventFlagGroup(); if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ || !outputQ->isValid() || !efGroup) { ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__, statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0, efGroup.get()); !outputQ->isValid()) { ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0); return INVALID_OPERATION; } Loading Loading @@ -225,8 +237,8 @@ status_t EffectHalAidl::process() { return INVALID_OPERATION; } ALOGD("%s %s consumed %zu produced %zu", __func__, mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead); ALOGD("%s %s consumed %zu produced %zu", __func__, effectName.c_str(), floatsToWrite, floatsToRead); return OK; } Loading media/libeffects/downmix/aidl/EffectDownmix.cpp +37 −36 Original line number Diff line number Diff line Loading @@ -71,42 +71,6 @@ ndk::ScopedAStatus DownmixImpl::getDescriptor(Descriptor* _aidl_return) { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) { RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); auto tag = param.getTag(); switch (tag) { case Parameter::common: RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setCommFailed"); break; case Parameter::deviceDescription: RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setDeviceFailed"); break; case Parameter::mode: RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setModeFailed"); break; case Parameter::source: RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setSourceFailed"); break; case Parameter::volumeStereo: RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed"); break; default: { LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "commonParamNotSupported"); } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) { RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); switch (command) { Loading Loading @@ -206,6 +170,43 @@ RetCode DownmixImpl::releaseContext() { return RetCode::SUCCESS; } void DownmixImpl::process() { /** * wait for the EventFlag without lock, it's ok because the mEfGroup pointer will not change * in the life cycle of workerThread (threadLoop). */ uint32_t efState = 0; if (!mEventFlag || ::android::OK != mEventFlag->wait(kEventFlagNotEmpty, &efState)) { LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag invalid"; } { std::lock_guard lg(mImplMutex); RETURN_VALUE_IF(!mImplContext, void(), "nullContext"); auto statusMQ = mImplContext->getStatusFmq(); auto inputMQ = mImplContext->getInputDataFmq(); auto outputMQ = mImplContext->getOutputDataFmq(); auto buffer = mImplContext->getWorkBuffer(); if (!inputMQ || !outputMQ) { return; } const auto availableToRead = inputMQ->availableToRead(); const auto availableToWrite = outputMQ->availableToWrite() * mImplContext->getInputFrameSize() / mImplContext->getOutputFrameSize(); auto processSamples = std::min(availableToRead, availableToWrite); if (processSamples) { inputMQ->read(buffer, processSamples); IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples); outputMQ->write(buffer, status.fmqProduced); statusMQ->writeBlocking(&status, 1); LOG(VERBOSE) << getEffectName() << __func__ << ": done processing, effect consumed " << status.fmqConsumed << " produced " << status.fmqProduced; } } } // Processing method running in EffectWorker thread. IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) { if (!mContext) { Loading media/libeffects/downmix/aidl/EffectDownmix.h +17 −12 Original line number Diff line number Diff line Loading @@ -34,21 +34,26 @@ class DownmixImpl final : public EffectImpl { LOG(DEBUG) << __func__; } ndk::ScopedAStatus commandImpl(CommandId command) override; ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override; ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override; ndk::ScopedAStatus setParameterCommon(const Parameter& param) override; ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override; ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) override; IEffect::Status effectProcessImpl(float* in, float* out, int process) override; std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override; RetCode releaseContext() override; std::shared_ptr<EffectContext> getContext() override { return mContext; } ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) REQUIRES(mImplMutex) override; ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) REQUIRES(mImplMutex) override; IEffect::Status effectProcessImpl(float* in, float* out, int process) REQUIRES(mImplMutex) override; std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) REQUIRES(mImplMutex) override; RetCode releaseContext() REQUIRES(mImplMutex) override; std::string getEffectName() override { return kEffectName; } // downmix override the process because of different input/output sample size requirement void process() override; private: std::shared_ptr<DownmixContext> mContext; ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific); std::shared_ptr<DownmixContext> mContext GUARDED_BY(mImplMutex); ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific) REQUIRES(mImplMutex); }; } // namespace aidl::android::hardware::audio::effect Loading
media/libaudiohal/impl/EffectConversionHelperAidl.cpp +21 −10 Original line number Diff line number Diff line Loading @@ -187,16 +187,7 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi IEffect::OpenEffectReturn openReturn; RETURN_STATUS_IF_ERROR( statusTFromBinderStatus(mEffect->open(common, std::nullopt, &openReturn))); if (mIsProxyEffect) { mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ(); mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ(); mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ(); } else { mStatusQ = std::make_shared<StatusMQ>(openReturn.statusMQ); mInputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ); mOutputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ); } updateMqs(openReturn); if (status_t status = updateEventFlags(); status != OK) { ALOGV("%s closing at status %d", __func__, status); Loading @@ -213,6 +204,18 @@ status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const voi return *static_cast<int32_t*>(pReplyData) = OK; } void EffectConversionHelperAidl::updateMqs(const IEffect::OpenEffectReturn& ret) { if (mIsProxyEffect) { mStatusQ = std::static_pointer_cast<EffectProxy>(mEffect)->getStatusMQ(); mInputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getInputMQ(); mOutputQ = std::static_pointer_cast<EffectProxy>(mEffect)->getOutputMQ(); } else { mStatusQ = std::make_shared<StatusMQ>(ret.statusMQ); mInputQ = std::make_shared<DataMQ>(ret.inputDataMQ); mOutputQ = std::make_shared<DataMQ>(ret.outputDataMQ); } } status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused, const void* pCmdData __unused, uint32_t* replySize, void* pReplyData) { Loading Loading @@ -505,5 +508,13 @@ Descriptor EffectConversionHelperAidl::getDescriptor() const { return desc; } status_t EffectConversionHelperAidl::reopen() { IEffect::OpenEffectReturn openReturn; RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->reopen(&openReturn))); updateMqs(openReturn); return OK; } } // namespace effect } // namespace android
media/libaudiohal/impl/EffectConversionHelperAidl.h +3 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ class EffectConversionHelperAidl { bool isBypassingOrTunnel() const; ::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const; status_t reopen(); protected: const int32_t mSessionId; Loading Loading @@ -108,6 +109,8 @@ class EffectConversionHelperAidl { std::shared_ptr<android::hardware::EventFlag> mEfGroup = nullptr; status_t updateEventFlags(); void updateMqs(const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn& ret); status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize, void* pReplyData); status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize, Loading
media/libaudiohal/impl/EffectHalAidl.cpp +21 −9 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ using ::aidl::android::aidl_utils::statusTFromBinderStatus; using ::aidl::android::hardware::audio::effect::Descriptor; using ::aidl::android::hardware::audio::effect::IEffect; using ::aidl::android::hardware::audio::effect::IFactory; using ::aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate; using ::aidl::android::hardware::audio::effect::State; namespace android { Loading Loading @@ -165,26 +166,37 @@ status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ status_t EffectHalAidl::process() { const std::string effectName = mConversion->getDescriptor().common.name; State state = State::INIT; if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() || state != State::PROCESSING) { ALOGI("%s skipping %s process because it's %s", __func__, mConversion->getDescriptor().common.name.c_str(), ALOGI("%s skipping %s process because it's %s", __func__, effectName.c_str(), mConversion->isBypassing() ? "bypassing" : aidl::android::hardware::audio::effect::toString(state).c_str()); return -ENODATA; } // check if the DataMq needs any update, timeout at 1ns to avoid being blocked auto efGroup = mConversion->getEventFlagGroup(); if (!efGroup) { ALOGE("%s invalid efGroup", __func__); return INVALID_OPERATION; } if (uint32_t efState = 0; ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState, 1 /* ns */, true /* retry */)) { ALOGI("%s %s receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str()); mConversion->reopen(); } auto statusQ = mConversion->getStatusMQ(); auto inputQ = mConversion->getInputMQ(); auto outputQ = mConversion->getOutputMQ(); auto efGroup = mConversion->getEventFlagGroup(); if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ || !outputQ->isValid() || !efGroup) { ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__, statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0, efGroup.get()); !outputQ->isValid()) { ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0); return INVALID_OPERATION; } Loading Loading @@ -225,8 +237,8 @@ status_t EffectHalAidl::process() { return INVALID_OPERATION; } ALOGD("%s %s consumed %zu produced %zu", __func__, mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead); ALOGD("%s %s consumed %zu produced %zu", __func__, effectName.c_str(), floatsToWrite, floatsToRead); return OK; } Loading
media/libeffects/downmix/aidl/EffectDownmix.cpp +37 −36 Original line number Diff line number Diff line Loading @@ -71,42 +71,6 @@ ndk::ScopedAStatus DownmixImpl::getDescriptor(Descriptor* _aidl_return) { return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) { RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); auto tag = param.getTag(); switch (tag) { case Parameter::common: RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setCommFailed"); break; case Parameter::deviceDescription: RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setDeviceFailed"); break; case Parameter::mode: RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setModeFailed"); break; case Parameter::source: RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setSourceFailed"); break; case Parameter::volumeStereo: RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed"); break; default: { LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag); return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "commonParamNotSupported"); } } return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) { RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); switch (command) { Loading Loading @@ -206,6 +170,43 @@ RetCode DownmixImpl::releaseContext() { return RetCode::SUCCESS; } void DownmixImpl::process() { /** * wait for the EventFlag without lock, it's ok because the mEfGroup pointer will not change * in the life cycle of workerThread (threadLoop). */ uint32_t efState = 0; if (!mEventFlag || ::android::OK != mEventFlag->wait(kEventFlagNotEmpty, &efState)) { LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag invalid"; } { std::lock_guard lg(mImplMutex); RETURN_VALUE_IF(!mImplContext, void(), "nullContext"); auto statusMQ = mImplContext->getStatusFmq(); auto inputMQ = mImplContext->getInputDataFmq(); auto outputMQ = mImplContext->getOutputDataFmq(); auto buffer = mImplContext->getWorkBuffer(); if (!inputMQ || !outputMQ) { return; } const auto availableToRead = inputMQ->availableToRead(); const auto availableToWrite = outputMQ->availableToWrite() * mImplContext->getInputFrameSize() / mImplContext->getOutputFrameSize(); auto processSamples = std::min(availableToRead, availableToWrite); if (processSamples) { inputMQ->read(buffer, processSamples); IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples); outputMQ->write(buffer, status.fmqProduced); statusMQ->writeBlocking(&status, 1); LOG(VERBOSE) << getEffectName() << __func__ << ": done processing, effect consumed " << status.fmqConsumed << " produced " << status.fmqProduced; } } } // Processing method running in EffectWorker thread. IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) { if (!mContext) { Loading
media/libeffects/downmix/aidl/EffectDownmix.h +17 −12 Original line number Diff line number Diff line Loading @@ -34,21 +34,26 @@ class DownmixImpl final : public EffectImpl { LOG(DEBUG) << __func__; } ndk::ScopedAStatus commandImpl(CommandId command) override; ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override; ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override; ndk::ScopedAStatus setParameterCommon(const Parameter& param) override; ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override; ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) override; IEffect::Status effectProcessImpl(float* in, float* out, int process) override; std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override; RetCode releaseContext() override; std::shared_ptr<EffectContext> getContext() override { return mContext; } ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) REQUIRES(mImplMutex) override; ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) REQUIRES(mImplMutex) override; IEffect::Status effectProcessImpl(float* in, float* out, int process) REQUIRES(mImplMutex) override; std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) REQUIRES(mImplMutex) override; RetCode releaseContext() REQUIRES(mImplMutex) override; std::string getEffectName() override { return kEffectName; } // downmix override the process because of different input/output sample size requirement void process() override; private: std::shared_ptr<DownmixContext> mContext; ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific); std::shared_ptr<DownmixContext> mContext GUARDED_BY(mImplMutex); ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific) REQUIRES(mImplMutex); }; } // namespace aidl::android::hardware::audio::effect