blob: 2e4e538b63c2c34358d685b4b32fcb4fa6a871ce [file] [log] [blame]
Shunkai Yao45905172022-08-24 18:14:02 +00001/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000017#define LOG_TAG "AHAL_EqualizerSw"
18#include <Utils.h>
Shunkai Yao45905172022-08-24 18:14:02 +000019#include <android-base/logging.h>
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000020#include <unordered_set>
Shunkai Yao45905172022-08-24 18:14:02 +000021
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000022#include "effect-impl/EffectUUID.h"
23#include "equalizer-impl/EqualizerSw.h"
24
25using android::hardware::audio::common::getFrameSizeInBytes;
Shunkai Yao45905172022-08-24 18:14:02 +000026
27namespace aidl::android::hardware::audio::effect {
28
Shunkai Yaoea24c1a2022-09-28 17:39:23 +000029extern "C" binder_exception_t createEffect(std::shared_ptr<IEffect>* instanceSpp) {
30 if (instanceSpp) {
31 *instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
32 LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
33 return EX_NONE;
34 } else {
35 LOG(ERROR) << __func__ << " invalid input parameter!";
36 return EX_ILLEGAL_ARGUMENT;
37 }
38}
39
40extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
41 State state;
42 ndk::ScopedAStatus status = instanceSp->getState(&state);
43 if (!status.isOk() || State::INIT != state) {
44 LOG(ERROR) << __func__ << " instance " << instanceSp.get()
45 << " in state: " << toString(state) << ", status: " << status.getDescription();
46 return EX_ILLEGAL_STATE;
47 }
48 LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
49 return EX_NONE;
50}
51
52ndk::ScopedAStatus EqualizerSw::open(const Parameter::Common& common,
53 const Parameter::Specific& specific,
54 OpenEffectReturn* _aidl_return) {
55 LOG(DEBUG) << __func__;
56 if (mState != State::INIT) {
57 LOG(WARNING) << __func__ << " eq already open";
58 return ndk::ScopedAStatus::ok();
59 }
60
61 // Set essential parameters before create worker thread.
62 setCommonParameter(common);
63 setSpecificParameter(specific);
64
65 LOG(DEBUG) << " common: " << common.toString() << " specific " << specific.toString();
66
67 auto& input = common.input;
68 auto& output = common.output;
69 size_t inputFrameSize = getFrameSizeInBytes(input.base.format, input.base.channelMask);
70 size_t outputFrameSize = getFrameSizeInBytes(output.base.format, output.base.channelMask);
71 if (!createFmq(1, input.frameCount * inputFrameSize, output.frameCount * outputFrameSize,
72 _aidl_return)) {
73 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
74 "FailedToCreateFmq");
75 }
76
77 // create the worker thread
78 if (RetCode::SUCCESS != mWorker->create(LOG_TAG)) {
79 LOG(ERROR) << __func__ << " created worker thread failed";
80 destroyFmq();
81 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
82 "FailedToCreateFmq");
83 }
84
85 mState = State::IDLE;
86 return ndk::ScopedAStatus::ok();
87}
88
89ndk::ScopedAStatus EqualizerSw::close() {
90 if (mState == State::INIT) {
91 LOG(WARNING) << __func__ << " instance already closed";
92 return ndk::ScopedAStatus::ok();
93 } else if (mState == State::PROCESSING) {
94 LOG(ERROR) << __func__ << " instance still processing";
95 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
96 "EqInstanceProcessing");
97 }
98
99 // stop the worker thread
100 mState = State::INIT;
101 mWorker->destroy();
102 destroyFmq();
Shunkai Yao45905172022-08-24 18:14:02 +0000103 LOG(DEBUG) << __func__;
104 return ndk::ScopedAStatus::ok();
105}
106
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000107ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
108 LOG(DEBUG) << __func__ << mDesc.toString();
Shunkai Yao45905172022-08-24 18:14:02 +0000109 *_aidl_return = mDesc;
110 return ndk::ScopedAStatus::ok();
111}
112
Shunkai Yaoea24c1a2022-09-28 17:39:23 +0000113ndk::ScopedAStatus EqualizerSw::command(CommandId in_commandId) {
114 LOG(DEBUG) << __func__ << ": receive command:" << toString(in_commandId);
115 if (mState == State::INIT) {
116 LOG(ERROR) << __func__ << ": instance not open yet";
117 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
118 "CommandStateError");
119 }
120 switch (in_commandId) {
121 case CommandId::START:
122 // start processing.
123 mState = State::PROCESSING;
124 mWorker->start();
125 LOG(DEBUG) << __func__ << " state: " << toString(mState);
126 return ndk::ScopedAStatus::ok();
127 case CommandId::STOP:
128 // stop processing.
129 mState = State::IDLE;
130 mWorker->stop();
131 LOG(DEBUG) << __func__ << " state: " << toString(mState);
132 return ndk::ScopedAStatus::ok();
133 case CommandId::RESET:
134 // TODO: reset buffer status.
135 mState = State::IDLE;
136 mWorker->stop();
137 LOG(DEBUG) << __func__ << " state: " << toString(mState);
138 return ndk::ScopedAStatus::ok();
139 default:
140 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
141 "CommandIdNotSupported");
142 }
143 return ndk::ScopedAStatus::ok();
144}
145
146ndk::ScopedAStatus EqualizerSw::setParameter(const Parameter& in_param) {
147 if (mState == State::INIT) {
148 LOG(ERROR) << __func__ << ": instance not open yet";
149 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "StateError");
150 }
151 LOG(DEBUG) << __func__ << " with: " << in_param.toString();
152 auto tag = in_param.getTag();
153 switch (tag) {
154 case Parameter::common: {
155 return setCommonParameter(in_param.get<Parameter::common>());
156 }
157 case Parameter::specific: {
158 return setSpecificParameter(in_param.get<Parameter::specific>());
159 }
160 default:
161 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
162 "ParameterNotSupported");
163 }
164}
165
166ndk::ScopedAStatus EqualizerSw::getParameter(const Parameter::Id& in_paramId,
167 Parameter* _aidl_return) {
168 LOG(DEBUG) << __func__ << in_paramId.toString();
169 auto tag = in_paramId.getTag();
170 switch (tag) {
171 case Parameter::Id::commonTag: {
172 _aidl_return->set<Parameter::common>(mCommonParam);
173 LOG(DEBUG) << __func__ << " get: " << _aidl_return->toString();
174 return ndk::ScopedAStatus::ok();
175 }
176 case Parameter::Id::specificTag: {
177 auto& id = in_paramId.get<Parameter::Id::specificTag>();
178 if (id != Parameter::Specific::equalizer) {
179 LOG(ERROR) << " unsupported parameter Id: " << in_paramId.toString();
180 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
181 EX_ILLEGAL_ARGUMENT, "Parameter::IdNotSupported");
182 }
183 Parameter::Specific specific;
184 specific.set<Parameter::Specific::equalizer>(mEqualizerParam);
185 _aidl_return->set<Parameter::specific>(specific);
186 LOG(DEBUG) << __func__ << _aidl_return->toString();
187 return ndk::ScopedAStatus::ok();
188 }
189 default:
190 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
191 "Parameter::IdNotSupported");
192 }
193}
194
195ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) {
196 *_aidl_return = mState;
197 return ndk::ScopedAStatus::ok();
198}
199
200/// Private methods.
201bool EqualizerSw::createFmq(int statusDepth, int inBufferSize, int outBufferSize,
202 OpenEffectReturn* ret) {
203 mStatusMQ = std::make_unique<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
204 mInputMQ = std::make_unique<DataMQ>(inBufferSize);
205 mOutputMQ = std::make_unique<DataMQ>(outBufferSize);
206
207 if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
208 LOG(ERROR) << __func__ << " created invalid FMQ";
209 return false;
210 }
211 ret->statusMQ = mStatusMQ->dupeDesc();
212 ret->inputDataMQ = mInputMQ->dupeDesc();
213 ret->outputDataMQ = mOutputMQ->dupeDesc();
214 return true;
215}
216
217void EqualizerSw::destroyFmq() {
218 mStatusMQ.reset(nullptr);
219 mInputMQ.reset(nullptr);
220 mOutputMQ.reset(nullptr);
221}
222
223ndk::ScopedAStatus EqualizerSw::setCommonParameter(const Parameter::Common& common) {
224 mCommonParam = common;
225 LOG(DEBUG) << __func__ << " set: " << mCommonParam.toString();
226 return ndk::ScopedAStatus::ok();
227}
228
229// TODO: implementation need change to save all parameters.
230ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& specific) {
231 if (Parameter::Specific::equalizer != specific.getTag()) {
232 LOG(ERROR) << " unsupported effect: " << specific.toString();
233 return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
234 "EffectNotSupported");
235 }
236
237 mEqualizerParam = specific.get<Parameter::Specific::equalizer>();
238 LOG(DEBUG) << __func__ << mEqualizerParam.toString();
239 return ndk::ScopedAStatus::ok();
240}
241
242void EqualizerSw::cleanUp() {
243 if (State::PROCESSING == mState) {
244 command(CommandId::STOP);
245 }
246 if (State::INIT != mState) {
247 close();
248 }
249}
250
251// Processing method running in worker thread.
252void EqualizerSwWorker::process() {
253 // TODO: add EQ processing with FMQ, should wait until data available before data processing.
254}
255
Shunkai Yao45905172022-08-24 18:14:02 +0000256} // namespace aidl::android::hardware::audio::effect