AIDL effect: Add Equalizer parameters implementation and vts

Bug: 238913361
Test: atest VtsHalAudioEffectTargetTest
atest VtsHalAudioEffectFactoryTargetTest
atest VtsHalEqualizerTargetTest

Change-Id: I94b2283ca2aa0e45715e1c9ac3ea6ad809ec2a2c
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
index 2e4e538..43fa206 100644
--- a/audio/aidl/default/equalizer/Equalizer.cpp
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -16,10 +16,12 @@
 
 #define LOG_TAG "AHAL_EqualizerSw"
 #include <Utils.h>
-#include <android-base/logging.h>
+#include <algorithm>
 #include <unordered_set>
 
-#include "effect-impl/EffectUUID.h"
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
 #include "equalizer-impl/EqualizerSw.h"
 
 using android::hardware::audio::common::getFrameSizeInBytes;
@@ -68,20 +70,26 @@
     auto& output = common.output;
     size_t inputFrameSize = getFrameSizeInBytes(input.base.format, input.base.channelMask);
     size_t outputFrameSize = getFrameSizeInBytes(output.base.format, output.base.channelMask);
-    if (!createFmq(1, input.frameCount * inputFrameSize, output.frameCount * outputFrameSize,
-                   _aidl_return)) {
+    mContext = std::make_shared<EqualizerSwContext>(1, input.frameCount * inputFrameSize,
+                                                    output.frameCount * outputFrameSize);
+    if (!mContext) {
+        LOG(ERROR) << __func__ << " created EqualizerSwContext failed";
         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
                                                                 "FailedToCreateFmq");
     }
+    setContext(mContext);
 
     // create the worker thread
-    if (RetCode::SUCCESS != mWorker->create(LOG_TAG)) {
+    if (RetCode::SUCCESS != createThread(LOG_TAG)) {
         LOG(ERROR) << __func__ << " created worker thread failed";
-        destroyFmq();
+        mContext.reset();
         return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
-                                                                "FailedToCreateFmq");
+                                                                "FailedToCreateWorker");
     }
 
+    _aidl_return->statusMQ = mContext->getStatusFmq()->dupeDesc();
+    _aidl_return->inputDataMQ = mContext->getInputDataFmq()->dupeDesc();
+    _aidl_return->outputDataMQ = mContext->getOutputDataFmq()->dupeDesc();
     mState = State::IDLE;
     return ndk::ScopedAStatus::ok();
 }
@@ -98,8 +106,9 @@
 
     // stop the worker thread
     mState = State::INIT;
-    mWorker->destroy();
-    destroyFmq();
+    destroyThread();
+    mContext.reset();
+
     LOG(DEBUG) << __func__;
     return ndk::ScopedAStatus::ok();
 }
@@ -121,19 +130,19 @@
         case CommandId::START:
             // start processing.
             mState = State::PROCESSING;
-            mWorker->start();
+            startThread();
             LOG(DEBUG) << __func__ << " state: " << toString(mState);
             return ndk::ScopedAStatus::ok();
         case CommandId::STOP:
             // stop processing.
             mState = State::IDLE;
-            mWorker->stop();
+            stopThread();
             LOG(DEBUG) << __func__ << " state: " << toString(mState);
             return ndk::ScopedAStatus::ok();
         case CommandId::RESET:
             // TODO: reset buffer status.
             mState = State::IDLE;
-            mWorker->stop();
+            stopThread();
             LOG(DEBUG) << __func__ << " state: " << toString(mState);
             return ndk::ScopedAStatus::ok();
         default:
@@ -173,23 +182,27 @@
             LOG(DEBUG) << __func__ << " get: " << _aidl_return->toString();
             return ndk::ScopedAStatus::ok();
         }
-        case Parameter::Id::specificTag: {
-            auto& id = in_paramId.get<Parameter::Id::specificTag>();
-            if (id != Parameter::Specific::equalizer) {
-                LOG(ERROR) << " unsupported parameter Id: " << in_paramId.toString();
-                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
-                        EX_ILLEGAL_ARGUMENT, "Parameter::IdNotSupported");
-            }
+        case Parameter::Id::specificId: {
+            auto& id = in_paramId.get<Parameter::Id::specificId>();
             Parameter::Specific specific;
-            specific.set<Parameter::Specific::equalizer>(mEqualizerParam);
+            ndk::ScopedAStatus status = getSpecificParameter(id, &specific);
+            if (!status.isOk()) {
+                LOG(ERROR) << __func__
+                           << " getSpecificParameter error: " << status.getDescription();
+                return status;
+            }
             _aidl_return->set<Parameter::specific>(specific);
             LOG(DEBUG) << __func__ << _aidl_return->toString();
             return ndk::ScopedAStatus::ok();
         }
-        default:
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "Parameter::IdNotSupported");
+        case Parameter::Id::vendorTag: {
+            LOG(DEBUG) << __func__ << " noop for vendor tag now";
+            return ndk::ScopedAStatus::ok();
+        }
     }
+    LOG(ERROR) << " unsupported tag: " << toString(tag);
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                            "Parameter:IdNotSupported");
 }
 
 ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) {
@@ -198,35 +211,12 @@
 }
 
 /// Private methods.
-bool EqualizerSw::createFmq(int statusDepth, int inBufferSize, int outBufferSize,
-                            OpenEffectReturn* ret) {
-    mStatusMQ = std::make_unique<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
-    mInputMQ = std::make_unique<DataMQ>(inBufferSize);
-    mOutputMQ = std::make_unique<DataMQ>(outBufferSize);
-
-    if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
-        LOG(ERROR) << __func__ << " created invalid FMQ";
-        return false;
-    }
-    ret->statusMQ = mStatusMQ->dupeDesc();
-    ret->inputDataMQ = mInputMQ->dupeDesc();
-    ret->outputDataMQ = mOutputMQ->dupeDesc();
-    return true;
-}
-
-void EqualizerSw::destroyFmq() {
-    mStatusMQ.reset(nullptr);
-    mInputMQ.reset(nullptr);
-    mOutputMQ.reset(nullptr);
-}
-
 ndk::ScopedAStatus EqualizerSw::setCommonParameter(const Parameter::Common& common) {
     mCommonParam = common;
     LOG(DEBUG) << __func__ << " set: " << mCommonParam.toString();
     return ndk::ScopedAStatus::ok();
 }
 
-// TODO: implementation need change to save all parameters.
 ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& specific) {
     if (Parameter::Specific::equalizer != specific.getTag()) {
         LOG(ERROR) << " unsupported effect: " << specific.toString();
@@ -234,9 +224,76 @@
                                                                 "EffectNotSupported");
     }
 
-    mEqualizerParam = specific.get<Parameter::Specific::equalizer>();
-    LOG(DEBUG) << __func__ << mEqualizerParam.toString();
-    return ndk::ScopedAStatus::ok();
+    auto& eqParam = specific.get<Parameter::Specific::equalizer>();
+    auto tag = eqParam.getTag();
+    switch (tag) {
+        case Equalizer::bandLevels: {
+            auto& bandLevels = eqParam.get<Equalizer::bandLevels>();
+            const auto& [minItem, maxItem] = std::minmax_element(
+                    bandLevels.begin(), bandLevels.end(),
+                    [](const auto& a, const auto& b) { return a.index < b.index; });
+            if (bandLevels.size() >= NUM_OF_BANDS || minItem->index < 0 ||
+                maxItem->index >= NUM_OF_BANDS) {
+                LOG(ERROR) << " bandLevels " << bandLevels.size() << "minIndex " << minItem->index
+                           << "maxIndex " << maxItem->index << " illegal ";
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                        "ExceedMaxBandNum");
+            }
+            mBandLevels = bandLevels;
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::preset: {
+            int preset = eqParam.get<Equalizer::preset>();
+            if (preset < 0 || preset >= NUM_OF_PRESETS) {
+                LOG(ERROR) << " preset: " << preset << " invalid";
+                return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                        "ExceedMaxBandNum");
+            }
+            mPreset = preset;
+            LOG(DEBUG) << __func__ << " preset set to " << mPreset;
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::vendor: {
+            LOG(DEBUG) << __func__ << " noop for vendor tag now";
+            return ndk::ScopedAStatus::ok();
+        }
+    }
+
+    LOG(ERROR) << __func__ << " unsupported eq param tag: " << toString(tag);
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                            "ParamNotSupported");
+}
+
+ndk::ScopedAStatus EqualizerSw::getSpecificParameter(Parameter::Specific::Id id,
+                                                     Parameter::Specific* specific) {
+    Equalizer eqParam;
+    auto tag = id.getTag();
+    if (tag != Parameter::Specific::Id::equalizerTag) {
+        LOG(ERROR) << " invalid tag: " << toString(tag);
+        return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                "UnsupportedTag");
+    }
+    auto eqTag = id.get<Parameter::Specific::Id::equalizerTag>();
+    switch (eqTag) {
+        case Equalizer::bandLevels: {
+            eqParam.set<Equalizer::bandLevels>(mBandLevels);
+            specific->set<Parameter::Specific::equalizer>(eqParam);
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::preset: {
+            eqParam.set<Equalizer::preset>(mPreset);
+            LOG(DEBUG) << __func__ << " preset " << mPreset;
+            specific->set<Parameter::Specific::equalizer>(eqParam);
+            return ndk::ScopedAStatus::ok();
+        }
+        case Equalizer::vendor: {
+            LOG(DEBUG) << __func__ << " noop for vendor tag now";
+            return ndk::ScopedAStatus::ok();
+        }
+    }
+    LOG(ERROR) << __func__ << " unsupported eq param: " << toString(eqTag);
+    return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                            "ParamNotSupported");
 }
 
 void EqualizerSw::cleanUp() {
@@ -248,9 +305,18 @@
     }
 }
 
-// Processing method running in worker thread.
-void EqualizerSwWorker::process() {
-    // TODO: add EQ processing with FMQ, should wait until data available before data processing.
+IEffect::Status EqualizerSw::status(binder_status_t status, size_t consumed, size_t produced) {
+    IEffect::Status ret;
+    ret.status = status;
+    ret.fmqByteConsumed = consumed;
+    ret.fmqByteProduced = produced;
+    return ret;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EqualizerSw::effectProcessImpl() {
+    // TODO: get data buffer and process.
+    return status(STATUS_OK, mContext->availableToRead(), mContext->availableToWrite());
 }
 
 }  // namespace aidl::android::hardware::audio::effect