1 /*
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
17 #include <cstddef>
18 #define LOG_TAG "EffectHalAidl"
19 //#define LOG_NDEBUG 0
20
21 #include <memory>
22
23 #include <error/expected_utils.h>
24 #include <media/AidlConversionCppNdk.h>
25 #include <media/AidlConversionEffect.h>
26 #include <media/AidlConversionUtil.h>
27 #include <media/EffectsFactoryApi.h>
28 #include <mediautils/TimeCheck.h>
29 #include <system/audio.h>
30 #include <system/audio_effects/effect_uuid.h>
31 #include <utils/Log.h>
32
33 #include "EffectHalAidl.h"
34 #include "EffectProxy.h"
35
36 #include <aidl/android/hardware/audio/effect/IEffect.h>
37
38 #include "effectsAidlConversion/AidlConversionAec.h"
39 #include "effectsAidlConversion/AidlConversionAgc1.h"
40 #include "effectsAidlConversion/AidlConversionAgc2.h"
41 #include "effectsAidlConversion/AidlConversionBassBoost.h"
42 #include "effectsAidlConversion/AidlConversionDownmix.h"
43 #include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
44 #include "effectsAidlConversion/AidlConversionEnvReverb.h"
45 #include "effectsAidlConversion/AidlConversionEq.h"
46 #include "effectsAidlConversion/AidlConversionHapticGenerator.h"
47 #include "effectsAidlConversion/AidlConversionLoudnessEnhancer.h"
48 #include "effectsAidlConversion/AidlConversionNoiseSuppression.h"
49 #include "effectsAidlConversion/AidlConversionPresetReverb.h"
50 #include "effectsAidlConversion/AidlConversionSpatializer.h"
51 #include "effectsAidlConversion/AidlConversionVendorExtension.h"
52 #include "effectsAidlConversion/AidlConversionVirtualizer.h"
53 #include "effectsAidlConversion/AidlConversionVisualizer.h"
54
55 using ::aidl::android::aidl_utils::statusTFromBinderStatus;
56 using ::aidl::android::hardware::audio::effect::Descriptor;
57 using ::aidl::android::hardware::audio::effect::IEffect;
58 using ::aidl::android::hardware::audio::effect::IFactory;
59 using ::aidl::android::hardware::audio::effect::State;
60
61 namespace android {
62 namespace effect {
63
EffectHalAidl(const std::shared_ptr<IFactory> & factory,const std::shared_ptr<IEffect> & effect,int32_t sessionId,int32_t ioId,const Descriptor & desc,bool isProxyEffect)64 EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
65 const std::shared_ptr<IEffect>& effect,
66 int32_t sessionId, int32_t ioId, const Descriptor& desc,
67 bool isProxyEffect)
68 : mFactory(factory),
69 mEffect(effect),
70 mSessionId(sessionId),
71 mIoId(ioId),
72 mIsProxyEffect(isProxyEffect) {
73 createAidlConversion(effect, sessionId, ioId, desc);
74 }
75
~EffectHalAidl()76 EffectHalAidl::~EffectHalAidl() {
77 if (mFactory && mEffect) {
78 if (mIsProxyEffect) {
79 std::static_pointer_cast<EffectProxy>(mEffect)->destroy();
80 } else {
81 mFactory->destroyEffect(mEffect);
82 }
83 }
84 }
85
createAidlConversion(std::shared_ptr<IEffect> effect,int32_t sessionId,int32_t ioId,const Descriptor & desc)86 status_t EffectHalAidl::createAidlConversion(
87 std::shared_ptr<IEffect> effect,
88 int32_t sessionId, int32_t ioId,
89 const Descriptor& desc) {
90 const auto& typeUuid = desc.common.id.type;
91 ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
92 if (typeUuid ==
93 ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
94 mConversion = std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId,
95 desc, mIsProxyEffect);
96 } else if (typeUuid == ::aidl::android::hardware::audio::effect::
97 getEffectTypeUuidAutomaticGainControlV1()) {
98 mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
99 desc, mIsProxyEffect);
100 } else if (typeUuid == ::aidl::android::hardware::audio::effect::
101 getEffectTypeUuidAutomaticGainControlV2()) {
102 mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
103 desc, mIsProxyEffect);
104 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
105 mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(
106 effect, sessionId, ioId, desc, mIsProxyEffect);
107 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
108 mConversion = std::make_unique<android::effect::AidlConversionDownmix>(
109 effect, sessionId, ioId, desc, mIsProxyEffect);
110 } else if (typeUuid ==
111 ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
112 mConversion = std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId,
113 desc, mIsProxyEffect);
114 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
115 mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(
116 effect, sessionId, ioId, desc, mIsProxyEffect);
117 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
118 mConversion = std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId,
119 desc, mIsProxyEffect);
120 } else if (typeUuid ==
121 ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
122 mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
123 effect, sessionId, ioId, desc, mIsProxyEffect);
124 } else if (typeUuid ==
125 ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
126 mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
127 effect, sessionId, ioId, desc, mIsProxyEffect);
128 } else if (typeUuid ==
129 ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
130 mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
131 effect, sessionId, ioId, desc, mIsProxyEffect);
132 } else if (typeUuid ==
133 ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
134 mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
135 effect, sessionId, ioId, desc, mIsProxyEffect);
136 } else if (typeUuid ==
137 ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
138 mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
139 effect, sessionId, ioId, desc, mIsProxyEffect);
140 } else if (typeUuid ==
141 ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
142 mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
143 effect, sessionId, ioId, desc, mIsProxyEffect);
144 } else if (typeUuid ==
145 ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
146 mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(
147 effect, sessionId, ioId, desc, mIsProxyEffect);
148 } else {
149 // For unknown UUID, use vendor extension implementation
150 mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
151 effect, sessionId, ioId, desc, mIsProxyEffect);
152 }
153 return OK;
154 }
155
setInBuffer(const sp<EffectBufferHalInterface> & buffer)156 status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
157 mInBuffer = buffer;
158 return OK;
159 }
160
setOutBuffer(const sp<EffectBufferHalInterface> & buffer)161 status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
162 mOutBuffer = buffer;
163 return OK;
164 }
165
166 // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
process()167 status_t EffectHalAidl::process() {
168 State state = State::INIT;
169 if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
170 state != State::PROCESSING) {
171 ALOGI("%s skipping %s process because it's %s", __func__,
172 mConversion->getDescriptor().common.name.c_str(),
173 mConversion->isBypassing()
174 ? "bypassing"
175 : aidl::android::hardware::audio::effect::toString(state).c_str());
176 return -ENODATA;
177 }
178
179 auto statusQ = mConversion->getStatusMQ();
180 auto inputQ = mConversion->getInputMQ();
181 auto outputQ = mConversion->getOutputMQ();
182 auto efGroup = mConversion->getEventFlagGroup();
183 if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
184 !outputQ->isValid() || !efGroup) {
185 ALOGE("%s invalid FMQ [Status %d I %d O %d] efGroup %p", __func__,
186 statusQ ? statusQ->isValid() : 0, inputQ ? inputQ->isValid() : 0,
187 outputQ ? outputQ->isValid() : 0, efGroup.get());
188 return INVALID_OPERATION;
189 }
190
191 size_t available = inputQ->availableToWrite();
192 size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
193 if (floatsToWrite == 0) {
194 ALOGE("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
195 mInBuffer->getSize() / sizeof(float), available);
196 return INVALID_OPERATION;
197 }
198 if (!mInBuffer->audioBuffer() ||
199 !inputQ->write((float*)mInBuffer->audioBuffer()->f32, floatsToWrite)) {
200 ALOGE("%s failed to write %zu floats from audiobuffer %p to inputQ [avail %zu]", __func__,
201 floatsToWrite, mInBuffer->audioBuffer(), inputQ->availableToWrite());
202 return INVALID_OPERATION;
203 }
204 efGroup->wake(aidl::android::hardware::audio::effect::kEventFlagNotEmpty);
205
206 IEffect::Status retStatus{};
207 if (!statusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
208 (size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
209 ALOGE("%s read status failed: %s", __func__, retStatus.toString().c_str());
210 return INVALID_OPERATION;
211 }
212
213 available = outputQ->availableToRead();
214 size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
215 if (floatsToRead == 0) {
216 ALOGE("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
217 mOutBuffer->getSize() / sizeof(float), available);
218 return INVALID_OPERATION;
219 }
220 // always read floating point data for AIDL
221 if (!mOutBuffer->audioBuffer() ||
222 !outputQ->read(mOutBuffer->audioBuffer()->f32, floatsToRead)) {
223 ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", __func__, floatsToRead,
224 mOutBuffer->audioBuffer());
225 return INVALID_OPERATION;
226 }
227
228 ALOGD("%s %s consumed %zu produced %zu", __func__,
229 mConversion->getDescriptor().common.name.c_str(), floatsToWrite, floatsToRead);
230 return OK;
231 }
232
233 // TODO: no one using, maybe deprecate this interface
processReverse()234 status_t EffectHalAidl::processReverse() {
235 ALOGW("%s not implemented yet", __func__);
236 return OK;
237 }
238
command(uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)239 status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
240 uint32_t* replySize, void* pReplyData) {
241 TIME_CHECK();
242 if (!mConversion) {
243 ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
244 return INVALID_OPERATION;
245 }
246
247 return mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
248 }
249
getDescriptor(effect_descriptor_t * pDescriptor)250 status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
251 TIME_CHECK();
252 if (pDescriptor == nullptr) {
253 ALOGE("%s null descriptor pointer", __func__);
254 return BAD_VALUE;
255 }
256 Descriptor aidlDesc;
257 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getDescriptor(&aidlDesc)));
258
259 *pDescriptor = VALUE_OR_RETURN_STATUS(
260 ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(aidlDesc));
261 return OK;
262 }
263
close()264 status_t EffectHalAidl::close() {
265 TIME_CHECK();
266 return statusTFromBinderStatus(mEffect->close());
267 }
268
dump(int fd)269 status_t EffectHalAidl::dump(int fd) {
270 TIME_CHECK();
271 return mEffect->dump(fd, nullptr, 0);
272 }
273
274 } // namespace effect
275 } // namespace android
276