• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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