Loading audio/aidl/default/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ cc_defaults { filegroup { name: "effectCommonFile", srcs: [ "EffectContext.cpp", "EffectThread.cpp", "EffectImpl.cpp", ], Loading audio/aidl/default/EffectContext.cpp 0 → 100644 +227 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <memory> #define LOG_TAG "AHAL_EffectContext" #include "effect-impl/EffectContext.h" #include "include/effect-impl/EffectTypes.h" using aidl::android::hardware::audio::common::getChannelCount; using aidl::android::hardware::audio::common::getFrameSizeInBytes; using aidl::android::hardware::audio::effect::IEffect; using aidl::android::media::audio::common::PcmType; using ::android::hardware::EventFlag; namespace aidl::android::hardware::audio::effect { EffectContext::EffectContext(size_t statusDepth, const Parameter::Common& common) { LOG_ALWAYS_FATAL_IF(RetCode::SUCCESS != setCommon(common), "illegalCommonParameter"); // in/outBuffer size in float (FMQ data format defined for DataMQ) size_t inBufferSizeInFloat = common.input.frameCount * mInputFrameSize / sizeof(float); size_t outBufferSizeInFloat = common.output.frameCount * mOutputFrameSize / sizeof(float); // only status FMQ use the EventFlag mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/); mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat); mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat); if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) { LOG(ERROR) << __func__ << " created invalid FMQ"; } ::android::status_t status = EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEfGroup); LOG_ALWAYS_FATAL_IF(status != ::android::OK || !mEfGroup, " create EventFlagGroup failed "); mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat)); } // reset buffer status by abandon input data in FMQ void EffectContext::resetBuffer() { auto buffer = static_cast<float*>(mWorkBuffer.data()); std::vector<IEffect::Status> status(mStatusMQ->availableToRead()); if (mInputMQ) { mInputMQ->read(buffer, mInputMQ->availableToRead()); } } void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) { if (!mInputMQ) { mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize / sizeof(float)); } if (!mOutputMQ) { mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize / sizeof(float)); } dupeFmq(effectRet); } void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) { if (effectRet) { effectRet->statusMQ = mStatusMQ->dupeDesc(); effectRet->inputDataMQ = mInputMQ->dupeDesc(); effectRet->outputDataMQ = mOutputMQ->dupeDesc(); } } float* EffectContext::getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); } std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const { return mStatusMQ; } std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const { return mInputMQ; } std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const { return mOutputMQ; } size_t EffectContext::getInputFrameSize() const { return mInputFrameSize; } size_t EffectContext::getOutputFrameSize() const { return mOutputFrameSize; } int EffectContext::getSessionId() const { return mCommon.session; } int EffectContext::getIoHandle() const { return mCommon.ioHandle; } RetCode EffectContext::setOutputDevice( const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) { mOutputDevice = device; return RetCode::SUCCESS; } std::vector<aidl::android::media::audio::common::AudioDeviceDescription> EffectContext::getOutputDevice() { return mOutputDevice; } RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) { mMode = mode; return RetCode::SUCCESS; } aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() { return mMode; } RetCode EffectContext::setAudioSource( const aidl::android::media::audio::common::AudioSource& source) { mSource = source; return RetCode::SUCCESS; } aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() { return mSource; } RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) { mVolumeStereo = volumeStereo; return RetCode::SUCCESS; } Parameter::VolumeStereo EffectContext::getVolumeStereo() { return mVolumeStereo; } RetCode EffectContext::setCommon(const Parameter::Common& common) { LOG(VERBOSE) << __func__ << common.toString(); auto& input = common.input; auto& output = common.output; if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT || output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) { LOG(ERROR) << __func__ << " illegal IO, input " << ::android::internal::ToString(input.base.format) << ", output " << ::android::internal::ToString(output.base.format); return RetCode::ERROR_ILLEGAL_PARAMETER; } if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) { return ret; } mInputChannelCount = getChannelCount(input.base.channelMask); mOutputChannelCount = getChannelCount(output.base.channelMask); if (mInputChannelCount == 0 || mOutputChannelCount == 0) { LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount << ", output " << mOutputChannelCount; return RetCode::ERROR_ILLEGAL_PARAMETER; } mCommon = common; return RetCode::SUCCESS; } Parameter::Common EffectContext::getCommon() { LOG(VERBOSE) << __func__ << mCommon.toString(); return mCommon; } EventFlag* EffectContext::getStatusEventFlag() { return mEfGroup; } RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) { const auto iFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes( common.input.base.format, common.input.base.channelMask); const auto oFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes( common.output.base.format, common.output.base.channelMask); bool needUpdateMq = false; if (mInputMQ && (mInputFrameSize != iFrameSize || mCommon.input.frameCount != common.input.frameCount)) { mInputMQ.reset(); needUpdateMq = true; } if (mOutputMQ && (mOutputFrameSize != oFrameSize || mCommon.output.frameCount != common.output.frameCount)) { mOutputMQ.reset(); needUpdateMq = true; } mInputFrameSize = iFrameSize; mOutputFrameSize = oFrameSize; if (needUpdateMq) { return notifyDataMqUpdate(); } return RetCode::SUCCESS; } RetCode EffectContext::notifyDataMqUpdate() { if (!mEfGroup) { LOG(ERROR) << __func__ << ": invalid EventFlag group"; return RetCode::ERROR_EVENT_FLAG_ERROR; } if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) { LOG(ERROR) << __func__ << ": wake failure with ret " << ret; return RetCode::ERROR_EVENT_FLAG_ERROR; } LOG(DEBUG) << __func__ << " : signal client for reopen"; return RetCode::SUCCESS; } } // namespace aidl::android::hardware::audio::effect audio/aidl/default/EffectImpl.cpp +119 −38 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <memory> #define LOG_TAG "AHAL_EffectImpl" #include "effect-impl/EffectImpl.h" #include "effect-impl/EffectTypes.h" Loading @@ -22,6 +23,7 @@ using aidl::android::hardware::audio::effect::IEffect; using aidl::android::hardware::audio::effect::State; using aidl::android::media::audio::common::PcmType; using ::android::hardware::EventFlag; extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) { State state; Loading @@ -45,50 +47,62 @@ ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common, RETURN_IF(common.input.base.format.pcm != common.output.base.format.pcm || common.input.base.format.pcm != PcmType::FLOAT_32_BIT, EX_ILLEGAL_ARGUMENT, "dataMustBe32BitsFloat"); std::lock_guard lg(mImplMutex); RETURN_OK_IF(mState != State::INIT); auto context = createContext(common); RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed"); mImplContext = createContext(common); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); mEventFlag = mImplContext->getStatusEventFlag(); if (specific.has_value()) { RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr"); } mState = State::IDLE; context->dupeFmq(ret); RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, mImplContext->dupeFmq(ret); RETURN_IF(createThread(getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, "FailedToCreateWorker"); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::reopen(OpenEffectReturn* ret) { std::lock_guard lg(mImplMutex); RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "alreadyClosed"); // TODO: b/302036943 add reopen implementation auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); context->dupeFmq(ret); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); mImplContext->dupeFmqWithReopen(ret); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::close() { { std::lock_guard lg(mImplMutex); RETURN_OK_IF(mState == State::INIT); RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing"); mState = State::INIT; } RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE, "notifyEventFlagFailed"); // stop the worker thread, ignore the return code RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, "FailedToDestroyWorker"); mState = State::INIT; RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, "FailedToCreateWorker"); { std::lock_guard lg(mImplMutex); releaseContext(); mImplContext.reset(); } LOG(DEBUG) << getEffectName() << __func__; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) { std::lock_guard lg(mImplMutex); LOG(VERBOSE) << getEffectName() << __func__ << " with: " << param.toString(); const auto tag = param.getTag(); const auto& tag = param.getTag(); switch (tag) { case Parameter::common: case Parameter::deviceDescription: Loading @@ -110,8 +124,8 @@ ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) { } ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) { auto tag = id.getTag(); switch (tag) { std::lock_guard lg(mImplMutex); switch (id.getTag()) { case Parameter::Id::commonTag: { RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get<Parameter::Id::commonTag>(), param), "CommonParamNotSupported"); Loading @@ -131,30 +145,30 @@ ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* } ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) { auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); auto tag = param.getTag(); const auto& tag = param.getTag(); switch (tag) { case Parameter::common: RETURN_IF(context->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS, RETURN_IF(mImplContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setCommFailed"); break; case Parameter::deviceDescription: RETURN_IF(context->setOutputDevice(param.get<Parameter::deviceDescription>()) != RETURN_IF(mImplContext->setOutputDevice(param.get<Parameter::deviceDescription>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setDeviceFailed"); break; case Parameter::mode: RETURN_IF(context->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS, RETURN_IF(mImplContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setModeFailed"); break; case Parameter::source: RETURN_IF(context->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS, RETURN_IF(mImplContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setSourceFailed"); break; case Parameter::volumeStereo: RETURN_IF(context->setVolumeStereo(param.get<Parameter::volumeStereo>()) != RETURN_IF(mImplContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed"); break; Loading @@ -169,28 +183,27 @@ ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) { } ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) { auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); switch (tag) { case Parameter::common: { param->set<Parameter::common>(context->getCommon()); param->set<Parameter::common>(mImplContext->getCommon()); break; } case Parameter::deviceDescription: { param->set<Parameter::deviceDescription>(context->getOutputDevice()); param->set<Parameter::deviceDescription>(mImplContext->getOutputDevice()); break; } case Parameter::mode: { param->set<Parameter::mode>(context->getAudioMode()); param->set<Parameter::mode>(mImplContext->getAudioMode()); break; } case Parameter::source: { param->set<Parameter::source>(context->getAudioSource()); param->set<Parameter::source>(mImplContext->getAudioSource()); break; } case Parameter::volumeStereo: { param->set<Parameter::volumeStereo>(context->getVolumeStereo()); param->set<Parameter::volumeStereo>(mImplContext->getVolumeStereo()); break; } default: { Loading @@ -202,30 +215,34 @@ ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Par return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::getState(State* state) { ndk::ScopedAStatus EffectImpl::getState(State* state) NO_THREAD_SAFETY_ANALYSIS { *state = mState; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::command(CommandId command) { RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError"); std::lock_guard lg(mImplMutex); RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen"); LOG(DEBUG) << getEffectName() << __func__ << ": receive command: " << toString(command) << " at state " << toString(mState); switch (command) { case CommandId::START: RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen"); RETURN_OK_IF(mState == State::PROCESSING); RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); startThread(); mState = State::PROCESSING; RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE, "notifyEventFlagFailed"); startThread(); break; case CommandId::STOP: case CommandId::RESET: RETURN_OK_IF(mState == State::IDLE); mState = State::IDLE; RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE, "notifyEventFlagFailed"); stopThread(); RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); mState = State::IDLE; break; default: LOG(ERROR) << getEffectName() << __func__ << " instance still processing"; Loading @@ -237,19 +254,41 @@ ndk::ScopedAStatus EffectImpl::command(CommandId command) { } ndk::ScopedAStatus EffectImpl::commandImpl(CommandId command) { auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); if (command == CommandId::RESET) { context->resetBuffer(); mImplContext->resetBuffer(); } return ndk::ScopedAStatus::ok(); } std::shared_ptr<EffectContext> EffectImpl::createContext(const Parameter::Common& common) { return std::make_shared<EffectContext>(1 /* statusMqDepth */, common); } RetCode EffectImpl::releaseContext() { if (mImplContext) { mImplContext.reset(); } return RetCode::SUCCESS; } void EffectImpl::cleanUp() { command(CommandId::STOP); close(); } RetCode EffectImpl::notifyEventFlag(uint32_t flag) { if (!mEventFlag) { LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag invalid"; return RetCode::ERROR_EVENT_FLAG_ERROR; } if (const auto ret = mEventFlag->wake(flag); ret != ::android::OK) { LOG(ERROR) << getEffectName() << __func__ << ": wake failure with ret " << ret; return RetCode::ERROR_EVENT_FLAG_ERROR; } return RetCode::SUCCESS; } IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) { IEffect::Status ret; ret.status = status; Loading @@ -258,6 +297,48 @@ IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size return ret; } void EffectImpl::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, 0 /* no timeout */, true /* retry */) || !(efState & kEventFlagNotEmpty)) { LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag - " << mEventFlag << " efState - " << std::hex << efState; return; } { std::lock_guard lg(mImplMutex); if (mState != State::PROCESSING) { LOG(DEBUG) << getEffectName() << " skip process in state: " << toString(mState); return; } 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; } auto processSamples = inputMQ->availableToRead(); 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; } } } // A placeholder processing implementation to copy samples from input to output IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int samples) { for (int i = 0; i < samples; i++) { Loading audio/aidl/default/EffectThread.cpp +4 −51 Original line number Diff line number Diff line Loading @@ -25,8 +25,6 @@ #include "effect-impl/EffectThread.h" #include "effect-impl/EffectTypes.h" using ::android::hardware::EventFlag; namespace aidl::android::hardware::audio::effect { EffectThread::EffectThread() { Loading @@ -38,31 +36,18 @@ EffectThread::~EffectThread() { LOG(DEBUG) << __func__ << " done"; } RetCode EffectThread::createThread(std::shared_ptr<EffectContext> context, const std::string& name, int priority) { RetCode EffectThread::createThread(const std::string& name, int priority) { if (mThread.joinable()) { LOG(WARNING) << mName << __func__ << " thread already created, no-op"; return RetCode::SUCCESS; } mName = name; mPriority = priority; { std::lock_guard lg(mThreadMutex); mStop = true; mExit = false; mThreadContext = std::move(context); auto statusMQ = mThreadContext->getStatusFmq(); EventFlag* efGroup = nullptr; ::android::status_t status = EventFlag::createEventFlag(statusMQ->getEventFlagWord(), &efGroup); if (status != ::android::OK || !efGroup) { LOG(ERROR) << mName << __func__ << " create EventFlagGroup failed " << status << " efGroup " << efGroup; return RetCode::ERROR_THREAD; } mEfGroup.reset(efGroup); // kickoff and wait for commands (CommandId::START/STOP) or IEffect.close from client mEfGroup->wake(kEventFlagNotEmpty); } mThread = std::thread(&EffectThread::threadLoop, this); Loading @@ -75,16 +60,12 @@ RetCode EffectThread::destroyThread() { std::lock_guard lg(mThreadMutex); mStop = mExit = true; } mCv.notify_one(); mCv.notify_one(); if (mThread.joinable()) { mThread.join(); } { std::lock_guard lg(mThreadMutex); mThreadContext.reset(); } LOG(DEBUG) << mName << __func__; return RetCode::SUCCESS; } Loading @@ -96,7 +77,6 @@ RetCode EffectThread::startThread() { mCv.notify_one(); } mEfGroup->wake(kEventFlagNotEmpty); LOG(DEBUG) << mName << __func__; return RetCode::SUCCESS; } Loading @@ -108,7 +88,6 @@ RetCode EffectThread::stopThread() { mCv.notify_one(); } mEfGroup->wake(kEventFlagNotEmpty); LOG(DEBUG) << mName << __func__; return RetCode::SUCCESS; } Loading @@ -117,13 +96,6 @@ void EffectThread::threadLoop() { pthread_setname_np(pthread_self(), mName.substr(0, kMaxTaskNameLen - 1).c_str()); setpriority(PRIO_PROCESS, 0, mPriority); while (true) { /** * 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; mEfGroup->wait(kEventFlagNotEmpty, &efState); { std::unique_lock l(mThreadMutex); ::android::base::ScopedLockAssertion lock_assertion(mThreadMutex); Loading @@ -132,27 +104,8 @@ void EffectThread::threadLoop() { LOG(INFO) << __func__ << " EXIT!"; return; } process_l(); } } } void EffectThread::process_l() { RETURN_VALUE_IF(!mThreadContext, void(), "nullContext"); auto statusMQ = mThreadContext->getStatusFmq(); auto inputMQ = mThreadContext->getInputDataFmq(); auto outputMQ = mThreadContext->getOutputDataFmq(); auto buffer = mThreadContext->getWorkBuffer(); auto processSamples = inputMQ->availableToRead(); if (processSamples) { inputMQ->read(buffer, processSamples); IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples); outputMQ->write(buffer, status.fmqProduced); statusMQ->writeBlocking(&status, 1); LOG(VERBOSE) << mName << __func__ << ": done processing, effect consumed " << status.fmqConsumed << " produced " << status.fmqProduced; process(); } } Loading audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp +0 −4 Original line number Diff line number Diff line Loading @@ -168,10 +168,6 @@ std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext( return mContext; } std::shared_ptr<EffectContext> AcousticEchoCancelerSw::getContext() { return mContext; } RetCode AcousticEchoCancelerSw::releaseContext() { if (mContext) { mContext.reset(); Loading Loading
audio/aidl/default/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -230,6 +230,7 @@ cc_defaults { filegroup { name: "effectCommonFile", srcs: [ "EffectContext.cpp", "EffectThread.cpp", "EffectImpl.cpp", ], Loading
audio/aidl/default/EffectContext.cpp 0 → 100644 +227 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <memory> #define LOG_TAG "AHAL_EffectContext" #include "effect-impl/EffectContext.h" #include "include/effect-impl/EffectTypes.h" using aidl::android::hardware::audio::common::getChannelCount; using aidl::android::hardware::audio::common::getFrameSizeInBytes; using aidl::android::hardware::audio::effect::IEffect; using aidl::android::media::audio::common::PcmType; using ::android::hardware::EventFlag; namespace aidl::android::hardware::audio::effect { EffectContext::EffectContext(size_t statusDepth, const Parameter::Common& common) { LOG_ALWAYS_FATAL_IF(RetCode::SUCCESS != setCommon(common), "illegalCommonParameter"); // in/outBuffer size in float (FMQ data format defined for DataMQ) size_t inBufferSizeInFloat = common.input.frameCount * mInputFrameSize / sizeof(float); size_t outBufferSizeInFloat = common.output.frameCount * mOutputFrameSize / sizeof(float); // only status FMQ use the EventFlag mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/); mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat); mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat); if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) { LOG(ERROR) << __func__ << " created invalid FMQ"; } ::android::status_t status = EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEfGroup); LOG_ALWAYS_FATAL_IF(status != ::android::OK || !mEfGroup, " create EventFlagGroup failed "); mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat)); } // reset buffer status by abandon input data in FMQ void EffectContext::resetBuffer() { auto buffer = static_cast<float*>(mWorkBuffer.data()); std::vector<IEffect::Status> status(mStatusMQ->availableToRead()); if (mInputMQ) { mInputMQ->read(buffer, mInputMQ->availableToRead()); } } void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) { if (!mInputMQ) { mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize / sizeof(float)); } if (!mOutputMQ) { mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize / sizeof(float)); } dupeFmq(effectRet); } void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) { if (effectRet) { effectRet->statusMQ = mStatusMQ->dupeDesc(); effectRet->inputDataMQ = mInputMQ->dupeDesc(); effectRet->outputDataMQ = mOutputMQ->dupeDesc(); } } float* EffectContext::getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); } std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const { return mStatusMQ; } std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const { return mInputMQ; } std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const { return mOutputMQ; } size_t EffectContext::getInputFrameSize() const { return mInputFrameSize; } size_t EffectContext::getOutputFrameSize() const { return mOutputFrameSize; } int EffectContext::getSessionId() const { return mCommon.session; } int EffectContext::getIoHandle() const { return mCommon.ioHandle; } RetCode EffectContext::setOutputDevice( const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) { mOutputDevice = device; return RetCode::SUCCESS; } std::vector<aidl::android::media::audio::common::AudioDeviceDescription> EffectContext::getOutputDevice() { return mOutputDevice; } RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) { mMode = mode; return RetCode::SUCCESS; } aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() { return mMode; } RetCode EffectContext::setAudioSource( const aidl::android::media::audio::common::AudioSource& source) { mSource = source; return RetCode::SUCCESS; } aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() { return mSource; } RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) { mVolumeStereo = volumeStereo; return RetCode::SUCCESS; } Parameter::VolumeStereo EffectContext::getVolumeStereo() { return mVolumeStereo; } RetCode EffectContext::setCommon(const Parameter::Common& common) { LOG(VERBOSE) << __func__ << common.toString(); auto& input = common.input; auto& output = common.output; if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT || output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) { LOG(ERROR) << __func__ << " illegal IO, input " << ::android::internal::ToString(input.base.format) << ", output " << ::android::internal::ToString(output.base.format); return RetCode::ERROR_ILLEGAL_PARAMETER; } if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) { return ret; } mInputChannelCount = getChannelCount(input.base.channelMask); mOutputChannelCount = getChannelCount(output.base.channelMask); if (mInputChannelCount == 0 || mOutputChannelCount == 0) { LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount << ", output " << mOutputChannelCount; return RetCode::ERROR_ILLEGAL_PARAMETER; } mCommon = common; return RetCode::SUCCESS; } Parameter::Common EffectContext::getCommon() { LOG(VERBOSE) << __func__ << mCommon.toString(); return mCommon; } EventFlag* EffectContext::getStatusEventFlag() { return mEfGroup; } RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) { const auto iFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes( common.input.base.format, common.input.base.channelMask); const auto oFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes( common.output.base.format, common.output.base.channelMask); bool needUpdateMq = false; if (mInputMQ && (mInputFrameSize != iFrameSize || mCommon.input.frameCount != common.input.frameCount)) { mInputMQ.reset(); needUpdateMq = true; } if (mOutputMQ && (mOutputFrameSize != oFrameSize || mCommon.output.frameCount != common.output.frameCount)) { mOutputMQ.reset(); needUpdateMq = true; } mInputFrameSize = iFrameSize; mOutputFrameSize = oFrameSize; if (needUpdateMq) { return notifyDataMqUpdate(); } return RetCode::SUCCESS; } RetCode EffectContext::notifyDataMqUpdate() { if (!mEfGroup) { LOG(ERROR) << __func__ << ": invalid EventFlag group"; return RetCode::ERROR_EVENT_FLAG_ERROR; } if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) { LOG(ERROR) << __func__ << ": wake failure with ret " << ret; return RetCode::ERROR_EVENT_FLAG_ERROR; } LOG(DEBUG) << __func__ << " : signal client for reopen"; return RetCode::SUCCESS; } } // namespace aidl::android::hardware::audio::effect
audio/aidl/default/EffectImpl.cpp +119 −38 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ * limitations under the License. */ #include <memory> #define LOG_TAG "AHAL_EffectImpl" #include "effect-impl/EffectImpl.h" #include "effect-impl/EffectTypes.h" Loading @@ -22,6 +23,7 @@ using aidl::android::hardware::audio::effect::IEffect; using aidl::android::hardware::audio::effect::State; using aidl::android::media::audio::common::PcmType; using ::android::hardware::EventFlag; extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) { State state; Loading @@ -45,50 +47,62 @@ ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common, RETURN_IF(common.input.base.format.pcm != common.output.base.format.pcm || common.input.base.format.pcm != PcmType::FLOAT_32_BIT, EX_ILLEGAL_ARGUMENT, "dataMustBe32BitsFloat"); std::lock_guard lg(mImplMutex); RETURN_OK_IF(mState != State::INIT); auto context = createContext(common); RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed"); mImplContext = createContext(common); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); mEventFlag = mImplContext->getStatusEventFlag(); if (specific.has_value()) { RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr"); } mState = State::IDLE; context->dupeFmq(ret); RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, mImplContext->dupeFmq(ret); RETURN_IF(createThread(getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, "FailedToCreateWorker"); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::reopen(OpenEffectReturn* ret) { std::lock_guard lg(mImplMutex); RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "alreadyClosed"); // TODO: b/302036943 add reopen implementation auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); context->dupeFmq(ret); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); mImplContext->dupeFmqWithReopen(ret); return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::close() { { std::lock_guard lg(mImplMutex); RETURN_OK_IF(mState == State::INIT); RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing"); mState = State::INIT; } RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE, "notifyEventFlagFailed"); // stop the worker thread, ignore the return code RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, "FailedToDestroyWorker"); mState = State::INIT; RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION, "FailedToCreateWorker"); { std::lock_guard lg(mImplMutex); releaseContext(); mImplContext.reset(); } LOG(DEBUG) << getEffectName() << __func__; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) { std::lock_guard lg(mImplMutex); LOG(VERBOSE) << getEffectName() << __func__ << " with: " << param.toString(); const auto tag = param.getTag(); const auto& tag = param.getTag(); switch (tag) { case Parameter::common: case Parameter::deviceDescription: Loading @@ -110,8 +124,8 @@ ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) { } ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) { auto tag = id.getTag(); switch (tag) { std::lock_guard lg(mImplMutex); switch (id.getTag()) { case Parameter::Id::commonTag: { RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get<Parameter::Id::commonTag>(), param), "CommonParamNotSupported"); Loading @@ -131,30 +145,30 @@ ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* } ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) { auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); auto tag = param.getTag(); const auto& tag = param.getTag(); switch (tag) { case Parameter::common: RETURN_IF(context->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS, RETURN_IF(mImplContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setCommFailed"); break; case Parameter::deviceDescription: RETURN_IF(context->setOutputDevice(param.get<Parameter::deviceDescription>()) != RETURN_IF(mImplContext->setOutputDevice(param.get<Parameter::deviceDescription>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setDeviceFailed"); break; case Parameter::mode: RETURN_IF(context->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS, RETURN_IF(mImplContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setModeFailed"); break; case Parameter::source: RETURN_IF(context->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS, RETURN_IF(mImplContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setSourceFailed"); break; case Parameter::volumeStereo: RETURN_IF(context->setVolumeStereo(param.get<Parameter::volumeStereo>()) != RETURN_IF(mImplContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed"); break; Loading @@ -169,28 +183,27 @@ ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) { } ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) { auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); switch (tag) { case Parameter::common: { param->set<Parameter::common>(context->getCommon()); param->set<Parameter::common>(mImplContext->getCommon()); break; } case Parameter::deviceDescription: { param->set<Parameter::deviceDescription>(context->getOutputDevice()); param->set<Parameter::deviceDescription>(mImplContext->getOutputDevice()); break; } case Parameter::mode: { param->set<Parameter::mode>(context->getAudioMode()); param->set<Parameter::mode>(mImplContext->getAudioMode()); break; } case Parameter::source: { param->set<Parameter::source>(context->getAudioSource()); param->set<Parameter::source>(mImplContext->getAudioSource()); break; } case Parameter::volumeStereo: { param->set<Parameter::volumeStereo>(context->getVolumeStereo()); param->set<Parameter::volumeStereo>(mImplContext->getVolumeStereo()); break; } default: { Loading @@ -202,30 +215,34 @@ ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Par return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::getState(State* state) { ndk::ScopedAStatus EffectImpl::getState(State* state) NO_THREAD_SAFETY_ANALYSIS { *state = mState; return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus EffectImpl::command(CommandId command) { RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError"); std::lock_guard lg(mImplMutex); RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen"); LOG(DEBUG) << getEffectName() << __func__ << ": receive command: " << toString(command) << " at state " << toString(mState); switch (command) { case CommandId::START: RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen"); RETURN_OK_IF(mState == State::PROCESSING); RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); startThread(); mState = State::PROCESSING; RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE, "notifyEventFlagFailed"); startThread(); break; case CommandId::STOP: case CommandId::RESET: RETURN_OK_IF(mState == State::IDLE); mState = State::IDLE; RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE, "notifyEventFlagFailed"); stopThread(); RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed"); mState = State::IDLE; break; default: LOG(ERROR) << getEffectName() << __func__ << " instance still processing"; Loading @@ -237,19 +254,41 @@ ndk::ScopedAStatus EffectImpl::command(CommandId command) { } ndk::ScopedAStatus EffectImpl::commandImpl(CommandId command) { auto context = getContext(); RETURN_IF(!context, EX_NULL_POINTER, "nullContext"); RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext"); if (command == CommandId::RESET) { context->resetBuffer(); mImplContext->resetBuffer(); } return ndk::ScopedAStatus::ok(); } std::shared_ptr<EffectContext> EffectImpl::createContext(const Parameter::Common& common) { return std::make_shared<EffectContext>(1 /* statusMqDepth */, common); } RetCode EffectImpl::releaseContext() { if (mImplContext) { mImplContext.reset(); } return RetCode::SUCCESS; } void EffectImpl::cleanUp() { command(CommandId::STOP); close(); } RetCode EffectImpl::notifyEventFlag(uint32_t flag) { if (!mEventFlag) { LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag invalid"; return RetCode::ERROR_EVENT_FLAG_ERROR; } if (const auto ret = mEventFlag->wake(flag); ret != ::android::OK) { LOG(ERROR) << getEffectName() << __func__ << ": wake failure with ret " << ret; return RetCode::ERROR_EVENT_FLAG_ERROR; } return RetCode::SUCCESS; } IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) { IEffect::Status ret; ret.status = status; Loading @@ -258,6 +297,48 @@ IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size return ret; } void EffectImpl::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, 0 /* no timeout */, true /* retry */) || !(efState & kEventFlagNotEmpty)) { LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag - " << mEventFlag << " efState - " << std::hex << efState; return; } { std::lock_guard lg(mImplMutex); if (mState != State::PROCESSING) { LOG(DEBUG) << getEffectName() << " skip process in state: " << toString(mState); return; } 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; } auto processSamples = inputMQ->availableToRead(); 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; } } } // A placeholder processing implementation to copy samples from input to output IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int samples) { for (int i = 0; i < samples; i++) { Loading
audio/aidl/default/EffectThread.cpp +4 −51 Original line number Diff line number Diff line Loading @@ -25,8 +25,6 @@ #include "effect-impl/EffectThread.h" #include "effect-impl/EffectTypes.h" using ::android::hardware::EventFlag; namespace aidl::android::hardware::audio::effect { EffectThread::EffectThread() { Loading @@ -38,31 +36,18 @@ EffectThread::~EffectThread() { LOG(DEBUG) << __func__ << " done"; } RetCode EffectThread::createThread(std::shared_ptr<EffectContext> context, const std::string& name, int priority) { RetCode EffectThread::createThread(const std::string& name, int priority) { if (mThread.joinable()) { LOG(WARNING) << mName << __func__ << " thread already created, no-op"; return RetCode::SUCCESS; } mName = name; mPriority = priority; { std::lock_guard lg(mThreadMutex); mStop = true; mExit = false; mThreadContext = std::move(context); auto statusMQ = mThreadContext->getStatusFmq(); EventFlag* efGroup = nullptr; ::android::status_t status = EventFlag::createEventFlag(statusMQ->getEventFlagWord(), &efGroup); if (status != ::android::OK || !efGroup) { LOG(ERROR) << mName << __func__ << " create EventFlagGroup failed " << status << " efGroup " << efGroup; return RetCode::ERROR_THREAD; } mEfGroup.reset(efGroup); // kickoff and wait for commands (CommandId::START/STOP) or IEffect.close from client mEfGroup->wake(kEventFlagNotEmpty); } mThread = std::thread(&EffectThread::threadLoop, this); Loading @@ -75,16 +60,12 @@ RetCode EffectThread::destroyThread() { std::lock_guard lg(mThreadMutex); mStop = mExit = true; } mCv.notify_one(); mCv.notify_one(); if (mThread.joinable()) { mThread.join(); } { std::lock_guard lg(mThreadMutex); mThreadContext.reset(); } LOG(DEBUG) << mName << __func__; return RetCode::SUCCESS; } Loading @@ -96,7 +77,6 @@ RetCode EffectThread::startThread() { mCv.notify_one(); } mEfGroup->wake(kEventFlagNotEmpty); LOG(DEBUG) << mName << __func__; return RetCode::SUCCESS; } Loading @@ -108,7 +88,6 @@ RetCode EffectThread::stopThread() { mCv.notify_one(); } mEfGroup->wake(kEventFlagNotEmpty); LOG(DEBUG) << mName << __func__; return RetCode::SUCCESS; } Loading @@ -117,13 +96,6 @@ void EffectThread::threadLoop() { pthread_setname_np(pthread_self(), mName.substr(0, kMaxTaskNameLen - 1).c_str()); setpriority(PRIO_PROCESS, 0, mPriority); while (true) { /** * 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; mEfGroup->wait(kEventFlagNotEmpty, &efState); { std::unique_lock l(mThreadMutex); ::android::base::ScopedLockAssertion lock_assertion(mThreadMutex); Loading @@ -132,27 +104,8 @@ void EffectThread::threadLoop() { LOG(INFO) << __func__ << " EXIT!"; return; } process_l(); } } } void EffectThread::process_l() { RETURN_VALUE_IF(!mThreadContext, void(), "nullContext"); auto statusMQ = mThreadContext->getStatusFmq(); auto inputMQ = mThreadContext->getInputDataFmq(); auto outputMQ = mThreadContext->getOutputDataFmq(); auto buffer = mThreadContext->getWorkBuffer(); auto processSamples = inputMQ->availableToRead(); if (processSamples) { inputMQ->read(buffer, processSamples); IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples); outputMQ->write(buffer, status.fmqProduced); statusMQ->writeBlocking(&status, 1); LOG(VERBOSE) << mName << __func__ << ": done processing, effect consumed " << status.fmqConsumed << " produced " << status.fmqProduced; process(); } } Loading
audio/aidl/default/acousticEchoCanceler/AcousticEchoCancelerSw.cpp +0 −4 Original line number Diff line number Diff line Loading @@ -168,10 +168,6 @@ std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext( return mContext; } std::shared_ptr<EffectContext> AcousticEchoCancelerSw::getContext() { return mContext; } RetCode AcousticEchoCancelerSw::releaseContext() { if (mContext) { mContext.reset(); Loading