Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f24f1a44 authored by Shunkai Yao's avatar Shunkai Yao Committed by Automerger Merge Worker
Browse files

Merge changes from topic "effect_reopen" into main am: 3eb2a2c1 am: 4aaefb88

parents 98d41708 4aaefb88
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -226,6 +226,7 @@ cc_defaults {
filegroup {
    name: "effectCommonFile",
    srcs: [
        "EffectContext.cpp",
        "EffectThread.cpp",
        "EffectImpl.cpp",
    ],
+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
+119 −38
Original line number Diff line number Diff line
@@ -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"
@@ -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;
@@ -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:
@@ -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");
@@ -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;
@@ -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: {
@@ -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";
@@ -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;
@@ -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++) {
+4 −51
Original line number Diff line number Diff line
@@ -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() {
@@ -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);
@@ -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;
}
@@ -96,7 +77,6 @@ RetCode EffectThread::startThread() {
        mCv.notify_one();
    }

    mEfGroup->wake(kEventFlagNotEmpty);
    LOG(DEBUG) << mName << __func__;
    return RetCode::SUCCESS;
}
@@ -108,7 +88,6 @@ RetCode EffectThread::stopThread() {
        mCv.notify_one();
    }

    mEfGroup->wake(kEventFlagNotEmpty);
    LOG(DEBUG) << mName << __func__;
    return RetCode::SUCCESS;
}
@@ -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);
@@ -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();
    }
}

+0 −4
Original line number Diff line number Diff line
@@ -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