AIDL effect: Add effect AIDL implementationi and vts test
Bug: 238913361
Test: atest VtsHalAudioEffectTargetTest; atest VtsHalAudioEffectFactoryTargetTest
Merged-In: If8000b7396360996bdfb8eb269bc3de543871673
Change-Id: If8000b7396360996bdfb8eb269bc3de543871673
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
index 8b157fa..2e4e538 100644
--- a/audio/aidl/default/equalizer/Equalizer.cpp
+++ b/audio/aidl/default/equalizer/Equalizer.cpp
@@ -14,27 +14,243 @@
* limitations under the License.
*/
-#define LOG_TAG "AHAL_Equalizer"
+#define LOG_TAG "AHAL_EqualizerSw"
+#include <Utils.h>
#include <android-base/logging.h>
+#include <unordered_set>
-#include "Equalizer.h"
+#include "effect-impl/EffectUUID.h"
+#include "equalizer-impl/EqualizerSw.h"
+
+using android::hardware::audio::common::getFrameSizeInBytes;
namespace aidl::android::hardware::audio::effect {
-ndk::ScopedAStatus Equalizer::open() {
+extern "C" binder_exception_t createEffect(std::shared_ptr<IEffect>* instanceSpp) {
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
+ 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) {
+ 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;
+}
+
+ndk::ScopedAStatus EqualizerSw::open(const Parameter::Common& common,
+ const Parameter::Specific& specific,
+ OpenEffectReturn* _aidl_return) {
+ LOG(DEBUG) << __func__;
+ if (mState != State::INIT) {
+ LOG(WARNING) << __func__ << " eq already open";
+ return ndk::ScopedAStatus::ok();
+ }
+
+ // Set essential parameters before create worker thread.
+ setCommonParameter(common);
+ setSpecificParameter(specific);
+
+ LOG(DEBUG) << " common: " << common.toString() << " specific " << specific.toString();
+
+ auto& input = common.input;
+ 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)) {
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
+ "FailedToCreateFmq");
+ }
+
+ // create the worker thread
+ if (RetCode::SUCCESS != mWorker->create(LOG_TAG)) {
+ LOG(ERROR) << __func__ << " created worker thread failed";
+ destroyFmq();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
+ "FailedToCreateFmq");
+ }
+
+ mState = State::IDLE;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::close() {
+ if (mState == State::INIT) {
+ LOG(WARNING) << __func__ << " instance already closed";
+ return ndk::ScopedAStatus::ok();
+ } else if (mState == State::PROCESSING) {
+ LOG(ERROR) << __func__ << " instance still processing";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
+ "EqInstanceProcessing");
+ }
+
+ // stop the worker thread
+ mState = State::INIT;
+ mWorker->destroy();
+ destroyFmq();
LOG(DEBUG) << __func__;
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Equalizer::close() {
- LOG(DEBUG) << __func__;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Equalizer::getDescriptor(Descriptor* _aidl_return) {
- LOG(DEBUG) << __func__ << "descriptor " << mDesc.toString();
+ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << mDesc.toString();
*_aidl_return = mDesc;
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus EqualizerSw::command(CommandId in_commandId) {
+ LOG(DEBUG) << __func__ << ": receive command:" << toString(in_commandId);
+ if (mState == State::INIT) {
+ LOG(ERROR) << __func__ << ": instance not open yet";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
+ "CommandStateError");
+ }
+ switch (in_commandId) {
+ case CommandId::START:
+ // start processing.
+ mState = State::PROCESSING;
+ mWorker->start();
+ LOG(DEBUG) << __func__ << " state: " << toString(mState);
+ return ndk::ScopedAStatus::ok();
+ case CommandId::STOP:
+ // stop processing.
+ mState = State::IDLE;
+ mWorker->stop();
+ LOG(DEBUG) << __func__ << " state: " << toString(mState);
+ return ndk::ScopedAStatus::ok();
+ case CommandId::RESET:
+ // TODO: reset buffer status.
+ mState = State::IDLE;
+ mWorker->stop();
+ LOG(DEBUG) << __func__ << " state: " << toString(mState);
+ return ndk::ScopedAStatus::ok();
+ default:
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "CommandIdNotSupported");
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::setParameter(const Parameter& in_param) {
+ if (mState == State::INIT) {
+ LOG(ERROR) << __func__ << ": instance not open yet";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "StateError");
+ }
+ LOG(DEBUG) << __func__ << " with: " << in_param.toString();
+ auto tag = in_param.getTag();
+ switch (tag) {
+ case Parameter::common: {
+ return setCommonParameter(in_param.get<Parameter::common>());
+ }
+ case Parameter::specific: {
+ return setSpecificParameter(in_param.get<Parameter::specific>());
+ }
+ default:
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "ParameterNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EqualizerSw::getParameter(const Parameter::Id& in_paramId,
+ Parameter* _aidl_return) {
+ LOG(DEBUG) << __func__ << in_paramId.toString();
+ auto tag = in_paramId.getTag();
+ switch (tag) {
+ case Parameter::Id::commonTag: {
+ _aidl_return->set<Parameter::common>(mCommonParam);
+ 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");
+ }
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::equalizer>(mEqualizerParam);
+ _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");
+ }
+}
+
+ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) {
+ *_aidl_return = mState;
+ return ndk::ScopedAStatus::ok();
+}
+
+/// 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();
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ }
+
+ mEqualizerParam = specific.get<Parameter::Specific::equalizer>();
+ LOG(DEBUG) << __func__ << mEqualizerParam.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+void EqualizerSw::cleanUp() {
+ if (State::PROCESSING == mState) {
+ command(CommandId::STOP);
+ }
+ if (State::INIT != mState) {
+ close();
+ }
+}
+
+// Processing method running in worker thread.
+void EqualizerSwWorker::process() {
+ // TODO: add EQ processing with FMQ, should wait until data available before data processing.
+}
+
} // namespace aidl::android::hardware::audio::effect