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

Commit 6afc8550 authored by Shunkai Yao's avatar Shunkai Yao
Browse files

AIDL effect: Add all aosp effects default implementation

Bug: 238913361
Test: atest VtsHalAudioEffectTargetTest
atest VtsHalAudioEffectFactoryTargetTest
atest VtsHalEqualizerTargetTest

Change-Id: I6825ba77ae0707f97e852f0faa52ce3486ba2af5
parent 82a6f7a8
Loading
Loading
Loading
Loading
+29 −20
Original line number Diff line number Diff line
@@ -68,10 +68,20 @@ cc_defaults {
    ],
    vendor: true,
    shared_libs: [
        "libaudioaidlcommon",
        "libbase",
        "libbinder_ndk",
        "libcutils",
        "libfmq",
        "liblog",
        "libutils",
        "android.hardware.common-V2-ndk",
        "android.hardware.common.fmq-V1-ndk",
        "android.hardware.audio.effect-V1-ndk",
        "libequalizer",
    ],
    header_libs: [
        "libaudioaidl_headers",
        "libsystem_headers",
    ],
    cflags: [
        "-Wall",
@@ -81,24 +91,12 @@ cc_defaults {
    ],
}

cc_library_static {
    name: "libaudioeffectserviceexampleimpl",
    defaults: ["aidlaudioeffectservice_defaults"],
    export_include_dirs: ["include"],
    srcs: [
        "EffectFactory.cpp",
    ],
    header_libs: [
        "libsystem_headers",
    ],
    visibility: [
        ":__subpackages__",
    ],
}

filegroup {
    name: "effectCommonFile",
    srcs: ["EffectThread.cpp"],
    srcs: [
        "EffectThread.cpp",
        "EffectImpl.cpp",
    ],
}

cc_binary {
@@ -107,10 +105,21 @@ cc_binary {
    init_rc: ["android.hardware.audio.effect.service-aidl.example.rc"],
    vintf_fragments: ["android.hardware.audio.effect.service-aidl.xml"],
    defaults: ["aidlaudioeffectservice_defaults"],
    static_libs: [
        "libaudioeffectserviceexampleimpl",
    shared_libs: [
        "libbassboostsw",
        "libdynamicsprocessingsw",
        "libequalizersw",
        "libhapticgeneratorsw",
        "libloudnessenhancersw",
        "libreverbsw",
        "libvirtualizersw",
        "libvisualizersw",
        "libvolumesw",
    ],
    srcs: [
        "EffectMain.cpp",
        "EffectFactory.cpp",
    ],
    srcs: ["EffectMain.cpp"],
}

cc_library_headers {
+82 −59
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
#include <dlfcn.h>

#include "effect-impl/EffectTypes.h"
#include "effect-impl/EffectUUID.h"
#include "effectFactory-impl/EffectFactory.h"

@@ -26,27 +27,21 @@ using aidl::android::media::audio::common::AudioUuid;
namespace aidl::android::hardware::audio::effect {

Factory::Factory() {
    std::function<void(void*)> dlClose = [](void* handle) -> void {
        if (handle && dlclose(handle)) {
            LOG(ERROR) << "dlclose failed " << dlerror();
        }
    };
    // TODO: implement this with audio_effect.xml.
    auto libHandle =
            std::unique_ptr<void, decltype(dlClose)>{dlopen("libequalizer.so", RTLD_LAZY), dlClose};
    if (!libHandle) {
        LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
        return;
    }

    LOG(DEBUG) << __func__ << " dlopen uuid: " << EqualizerSwImplUUID.toString() << " handle "
               << libHandle;
    mEffectLibMap.insert({EqualizerSwImplUUID, std::make_pair(std::move(libHandle), nullptr)});

    Descriptor::Identity id;
    id.type = EqualizerTypeUUID;
    id.uuid = EqualizerSwImplUUID;
    mIdentityList.push_back(id);
    // TODO: get list of library UUID and name from audio_effect.xml.
    openEffectLibrary(EqualizerTypeUUID, EqualizerSwImplUUID, std::nullopt, "libequalizersw.so");
    openEffectLibrary(EqualizerTypeUUID, EqualizerBundleImplUUID, std::nullopt, "libbundleaidl.so");
    openEffectLibrary(BassBoostTypeUUID, BassBoostSwImplUUID, std::nullopt, "libbassboostsw.so");
    openEffectLibrary(DynamicsProcessingTypeUUID, DynamicsProcessingSwImplUUID, std::nullopt,
                      "libdynamicsprocessingsw.so");
    openEffectLibrary(HapticGeneratorTypeUUID, HapticGeneratorSwImplUUID, std::nullopt,
                      "libhapticgeneratorsw.so");
    openEffectLibrary(LoudnessEnhancerTypeUUID, LoudnessEnhancerSwImplUUID, std::nullopt,
                      "libloudnessenhancersw.so");
    openEffectLibrary(ReverbTypeUUID, ReverbSwImplUUID, std::nullopt, "libreverbsw.so");
    openEffectLibrary(VirtualizerTypeUUID, VirtualizerSwImplUUID, std::nullopt,
                      "libvirtualizersw.so");
    openEffectLibrary(VisualizerTypeUUID, VisualizerSwImplUUID, std::nullopt, "libvisualizersw.so");
    openEffectLibrary(VolumeTypeUUID, VolumeSwImplUUID, std::nullopt, "libvolumesw.so");
}

Factory::~Factory() {
@@ -64,11 +59,15 @@ Factory::~Factory() {

ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
                                         const std::optional<AudioUuid>& in_impl_uuid,
                                         const std::optional<AudioUuid>& in_proxy_uuid,
                                         std::vector<Descriptor::Identity>* _aidl_return) {
    std::copy_if(mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return),
    std::copy_if(
            mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return),
            [&](auto& desc) {
                return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) &&
                            (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid);
                       (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid) &&
                       (!in_proxy_uuid.has_value() ||
                        (desc.proxy.has_value() && in_proxy_uuid.value() == desc.proxy.value()));
            });
    return ndk::ScopedAStatus::ok();
}
@@ -96,21 +95,19 @@ ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type
ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
                                         std::shared_ptr<IEffect>* _aidl_return) {
    LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
    if (in_impl_uuid == EqualizerSwImplUUID) {
    if (mEffectLibMap.count(in_impl_uuid)) {
        auto& lib = mEffectLibMap[in_impl_uuid];
        // didn't do dlsym yet
        if (nullptr == lib.second) {
            void* libHandle = lib.first.get();
                struct effect_interface_s intf = {
                        .createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"),
                        .destroyEffectFunc =
                                (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect")};
                auto dlInterface = std::make_unique<struct effect_interface_s>(intf);
            auto dlInterface = std::make_unique<struct effect_dl_interface_s>();
            dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect");
            dlInterface->destroyEffectFunc =
                    (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect");
            if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
                LOG(ERROR) << __func__
                           << ": create or destroy symbol not exist in library: " << libHandle
                               << "!";
                           << " with dlerror: " << dlerror();
                return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
            }
            lib.second = std::move(dlInterface);
@@ -118,7 +115,7 @@ ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,

        auto& libInterface = lib.second;
        std::shared_ptr<IEffect> effectSp;
            RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&effectSp));
        RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&in_impl_uuid, &effectSp));
        if (!effectSp) {
            LOG(ERROR) << __func__ << ": library created null instance without return error!";
            return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
@@ -131,10 +128,6 @@ ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
        LOG(ERROR) << __func__ << ": library doesn't exist";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    } else {
        LOG(ERROR) << __func__ << ": UUID not supported";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }
    return ndk::ScopedAStatus::ok();
}

@@ -179,4 +172,34 @@ ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_han
    return status;
}

void Factory::openEffectLibrary(const AudioUuid& type, const AudioUuid& impl,
                                const std::optional<AudioUuid>& proxy, const std::string& libName) {
    std::function<void(void*)> dlClose = [](void* handle) -> void {
        if (handle && dlclose(handle)) {
            LOG(ERROR) << "dlclose failed " << dlerror();
        }
    };

    auto libHandle =
            std::unique_ptr<void, decltype(dlClose)>{dlopen(libName.c_str(), RTLD_LAZY), dlClose};
    if (!libHandle) {
        LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
        return;
    }

    LOG(DEBUG) << __func__ << " dlopen lib:" << libName << " for uuid:\ntype:" << type.toString()
               << "\nimpl:" << impl.toString()
               << "\nproxy:" << (proxy.has_value() ? proxy.value().toString() : "null")
               << "\nhandle:" << libHandle;
    mEffectLibMap.insert({impl, std::make_pair(std::move(libHandle), nullptr)});

    Descriptor::Identity id;
    id.type = type;
    id.uuid = impl;
    if (proxy.has_value()) {
        id.proxy = proxy.value();
    }
    mIdentityList.push_back(id);
}

}  // namespace aidl::android::hardware::audio::effect
+256 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 */

#define LOG_TAG "AHAL_EffectImpl"
#include "effect-impl/EffectImpl.h"
#include "effect-impl/EffectTypes.h"
#include "include/effect-impl/EffectTypes.h"

namespace aidl::android::hardware::audio::effect {

ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common,
                                    const std::optional<Parameter::Specific>& specific,
                                    OpenEffectReturn* ret) {
    LOG(DEBUG) << __func__;
    {
        std::lock_guard lg(mMutex);
        RETURN_OK_IF(mState != State::INIT);
        mContext = createContext(common);
        RETURN_IF(!mContext, EX_ILLEGAL_ARGUMENT, "createContextFailed");
        setContext(mContext);
    }

    RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
    if (specific.has_value()) {
        RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
    }

    RETURN_IF(createThread(LOG_TAG) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
              "FailedToCreateWorker");

    {
        std::lock_guard lg(mMutex);
        mContext->dupeFmq(ret);
        mState = State::IDLE;
    }
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus EffectImpl::close() {
    std::lock_guard lg(mMutex);
    RETURN_OK_IF(mState == State::INIT);
    RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing");

    // stop the worker thread, ignore the return code
    RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
              "FailedToDestroyWorker");
    RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
              "FailedToCreateWorker");
    mState = State::INIT;
    LOG(DEBUG) << __func__;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
    LOG(DEBUG) << __func__ << " with: " << param.toString();

    auto tag = param.getTag();
    switch (tag) {
        case Parameter::common:
        case Parameter::deviceDescription:
        case Parameter::mode:
        case Parameter::source:
            FALLTHROUGH_INTENDED;
        case Parameter::volumeStereo:
            return setParameterCommon(param);
        case Parameter::specific: {
            return setParameterSpecific(param.get<Parameter::specific>());
        }
        default: {
            LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                    "ParameterNotSupported");
        }
    }
}

ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) {
    LOG(DEBUG) << __func__ << id.toString();
    auto tag = id.getTag();
    switch (tag) {
        case Parameter::Id::commonTag: {
            RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get<Parameter::Id::commonTag>(), param),
                                     "CommonParamNotSupported");
            break;
        }
        case Parameter::Id::vendorEffectTag: {
            LOG(DEBUG) << __func__ << " noop for vendor tag";
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                    "vendortagNotSupported");
        }
        default: {
            Parameter::Specific specific;
            RETURN_IF_ASTATUS_NOT_OK(getParameterSpecific(id, &specific), "SpecParamNotSupported");
            param->set<Parameter::specific>(specific);
            break;
        }
    }
    LOG(DEBUG) << __func__ << param->toString();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) {
    std::lock_guard lg(mMutex);
    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 EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) {
    std::lock_guard lg(mMutex);
    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
    switch (tag) {
        case Parameter::common: {
            param->set<Parameter::common>(mContext->getCommon());
            break;
        }
        case Parameter::deviceDescription: {
            param->set<Parameter::deviceDescription>(mContext->getOutputDevice());
            break;
        }
        case Parameter::mode: {
            param->set<Parameter::mode>(mContext->getAudioMode());
            break;
        }
        case Parameter::source: {
            param->set<Parameter::source>(mContext->getAudioSource());
            break;
        }
        case Parameter::volumeStereo: {
            param->set<Parameter::volumeStereo>(mContext->getVolumeStereo());
            break;
        }
        default: {
            LOG(DEBUG) << __func__ << " unsupported tag " << toString(tag);
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                    "tagNotSupported");
        }
    }
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus EffectImpl::getState(State* state) {
    std::lock_guard lg(mMutex);
    *state = mState;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus EffectImpl::command(CommandId command) {
    std::lock_guard lg(mMutex);
    LOG(DEBUG) << __func__ << ": receive command: " << toString(command) << " at state "
               << toString(mState);
    RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError");
    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");

    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(commandStart(), "commandStartFailed");
            mState = State::PROCESSING;
            startThread();
            return ndk::ScopedAStatus::ok();
        case CommandId::STOP:
            RETURN_OK_IF(mState == State::IDLE);
            mState = State::IDLE;
            RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
            stopThread();
            return ndk::ScopedAStatus::ok();
        case CommandId::RESET:
            RETURN_OK_IF(mState == State::IDLE);
            mState = State::IDLE;
            RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
            stopThread();
            mContext->resetBuffer();
            return ndk::ScopedAStatus::ok();
        default:
            LOG(ERROR) << __func__ << " instance still processing";
            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
                                                                    "CommandIdNotSupported");
    }
    LOG(DEBUG) << __func__ << " transfer to state: " << toString(mState);
    return ndk::ScopedAStatus::ok();
}

void EffectImpl::cleanUp() {
    command(CommandId::STOP);
    close();
}

IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) {
    IEffect::Status ret;
    ret.status = status;
    ret.fmqConsumed = consumed;
    ret.fmqProduced = produced;
    return ret;
}

// A placeholder processing implementation to copy samples from input to output
IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int processSamples) {
    // lock before access context/parameters
    std::lock_guard lg(mMutex);
    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
    RETURN_VALUE_IF(!mContext, status, "nullContext");
    auto frameSize = mContext->getInputFrameSize();
    RETURN_VALUE_IF(0 == frameSize, status, "frameSizeIs0");
    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << processSamples
               << " frames " << processSamples * sizeof(float) / frameSize;
    for (int i = 0; i < processSamples; i++) {
        *out++ = *in++;
    }
    LOG(DEBUG) << __func__ << " done processing " << processSamples << " samples";
    return {STATUS_OK, processSamples, processSamples};
}
}  // namespace aidl::android::hardware::audio::effect
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.
 */

package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "hardware_interfaces_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["hardware_interfaces_license"],
}

cc_library_shared {
    name: "libbassboostsw",
    defaults: [
        "aidlaudioeffectservice_defaults",
        "latest_android_media_audio_common_types_ndk_shared",
        "latest_android_hardware_audio_effect_ndk_shared",
    ],
    srcs: [
        "BassBoostSw.cpp",
        ":effectCommonFile",
    ],
    visibility: [
        "//hardware/interfaces/audio/aidl/default",
    ],
}
+118 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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 <cstddef>
#define LOG_TAG "AHAL_BassBoostSw"
#include <Utils.h>
#include <algorithm>
#include <unordered_set>

#include <android-base/logging.h>
#include <fmq/AidlMessageQueue.h>

#include "BassBoostSw.h"

using aidl::android::hardware::audio::effect::BassBoostSw;
using aidl::android::hardware::audio::effect::BassBoostSwImplUUID;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioUuid;

extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
                                           std::shared_ptr<IEffect>* instanceSpp) {
    if (!in_impl_uuid || *in_impl_uuid != BassBoostSwImplUUID) {
        LOG(ERROR) << __func__ << "uuid not supported";
        return EX_ILLEGAL_ARGUMENT;
    }
    if (instanceSpp) {
        *instanceSpp = ndk::SharedRefBase::make<BassBoostSw>();
        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
        return EX_NONE;
    } else {
        LOG(ERROR) << __func__ << " invalid input parameter!";
        return EX_ILLEGAL_ARGUMENT;
    }
}

extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
    if (!instanceSp) {
        return EX_NONE;
    }
    State state;
    ndk::ScopedAStatus status = instanceSp->getState(&state);
    if (!status.isOk() || State::INIT != state) {
        LOG(ERROR) << __func__ << " instance " << instanceSp.get()
                   << " in state: " << toString(state) << ", status: " << status.getDescription();
        return EX_ILLEGAL_STATE;
    }
    LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
    return EX_NONE;
}

namespace aidl::android::hardware::audio::effect {

ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
    LOG(DEBUG) << __func__ << kDescriptor.toString();
    *_aidl_return = kDescriptor;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific& specific) {
    RETURN_IF(Parameter::Specific::bassBoost != specific.getTag(), EX_ILLEGAL_ARGUMENT,
              "EffectNotSupported");
    std::lock_guard lg(mMutex);
    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");

    mSpecificParam = specific.get<Parameter::Specific::bassBoost>();
    LOG(DEBUG) << __func__ << " success with: " << specific.toString();
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BassBoostSw::getParameterSpecific(const Parameter::Id& id,
                                                     Parameter::Specific* specific) {
    auto tag = id.getTag();
    RETURN_IF(Parameter::Id::bassBoostTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
    specific->set<Parameter::Specific::bassBoost>(mSpecificParam);
    return ndk::ScopedAStatus::ok();
}

std::shared_ptr<EffectContext> BassBoostSw::createContext(const Parameter::Common& common) {
    if (mContext) {
        LOG(DEBUG) << __func__ << " context already exist";
        return mContext;
    }
    mContext = std::make_shared<BassBoostSwContext>(1 /* statusFmqDepth */, common);
    return mContext;
}

RetCode BassBoostSw::releaseContext() {
    if (mContext) {
        mContext.reset();
    }
    return RetCode::SUCCESS;
}

// Processing method running in EffectWorker thread.
IEffect::Status BassBoostSw::effectProcessImpl(float* in, float* out, int process) {
    // TODO: get data buffer and process.
    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
    for (int i = 0; i < process; i++) {
        *out++ = *in++;
    }
    return {STATUS_OK, process, process};
}

}  // namespace aidl::android::hardware::audio::effect
Loading