xref: /aosp_15_r20/frameworks/av/media/libaudiohal/impl/EffectHalAidl.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <cstddef>
18*ec779b8eSAndroid Build Coastguard Worker #include <cstring>
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "EffectHalAidl"
20*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include <memory>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include <audio_utils/primitives.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <error/expected_utils.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/AidlConversionCppNdk.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <media/AidlConversionEffect.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <media/AidlConversionUtil.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <media/EffectsFactoryApi.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <mediautils/TimeCheck.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <system/audio.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <system/audio_effects/effect_uuid.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
34*ec779b8eSAndroid Build Coastguard Worker 
35*ec779b8eSAndroid Build Coastguard Worker #include "EffectHalAidl.h"
36*ec779b8eSAndroid Build Coastguard Worker #include "EffectProxy.h"
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker #include <aidl/android/hardware/audio/effect/IEffect.h>
39*ec779b8eSAndroid Build Coastguard Worker 
40*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionAec.h"
41*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionAgc1.h"
42*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionAgc2.h"
43*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionBassBoost.h"
44*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionDownmix.h"
45*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
46*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionEnvReverb.h"
47*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionEq.h"
48*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionHapticGenerator.h"
49*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionLoudnessEnhancer.h"
50*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionNoiseSuppression.h"
51*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionPresetReverb.h"
52*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionSpatializer.h"
53*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionVendorExtension.h"
54*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionVirtualizer.h"
55*ec779b8eSAndroid Build Coastguard Worker #include "effectsAidlConversion/AidlConversionVisualizer.h"
56*ec779b8eSAndroid Build Coastguard Worker 
57*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::aidl_utils::statusTFromBinderStatus;
58*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::CommandId;
59*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::Descriptor;
60*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::IEffect;
61*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::IFactory;
62*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::kEventFlagDataMqNotEmpty;
63*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate;
64*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::kEventFlagNotEmpty;
65*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::kReopenSupportedVersion;
66*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::State;
67*ec779b8eSAndroid Build Coastguard Worker 
68*ec779b8eSAndroid Build Coastguard Worker namespace android {
69*ec779b8eSAndroid Build Coastguard Worker namespace effect {
70*ec779b8eSAndroid Build Coastguard Worker 
EffectHalAidl(const std::shared_ptr<IFactory> & factory,const std::shared_ptr<IEffect> & effect,int32_t sessionId,int32_t ioId,const Descriptor & desc,bool isProxyEffect)71*ec779b8eSAndroid Build Coastguard Worker EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
72*ec779b8eSAndroid Build Coastguard Worker                              const std::shared_ptr<IEffect>& effect, int32_t sessionId,
73*ec779b8eSAndroid Build Coastguard Worker                              int32_t ioId, const Descriptor& desc, bool isProxyEffect)
74*ec779b8eSAndroid Build Coastguard Worker     : mFactory(factory),
75*ec779b8eSAndroid Build Coastguard Worker       mEffect(effect),
76*ec779b8eSAndroid Build Coastguard Worker       mSessionId(sessionId),
77*ec779b8eSAndroid Build Coastguard Worker       mIoId(ioId),
78*ec779b8eSAndroid Build Coastguard Worker       mIsProxyEffect(isProxyEffect),
79*ec779b8eSAndroid Build Coastguard Worker       mHalVersion([factory]() {
80*ec779b8eSAndroid Build Coastguard Worker           int version = 0;
81*ec779b8eSAndroid Build Coastguard Worker           // use factory HAL version because effect can be an EffectProxy instance
82*ec779b8eSAndroid Build Coastguard Worker           return factory->getInterfaceVersion(&version).isOk() ? version : 0;
83*ec779b8eSAndroid Build Coastguard Worker       }()),
84*ec779b8eSAndroid Build Coastguard Worker       mEventFlagDataMqNotEmpty(mHalVersion >= kReopenSupportedVersion ? kEventFlagDataMqNotEmpty
85*ec779b8eSAndroid Build Coastguard Worker                                                                       : kEventFlagNotEmpty) {
86*ec779b8eSAndroid Build Coastguard Worker     assert(mFactory != nullptr);
87*ec779b8eSAndroid Build Coastguard Worker     assert(mEffect != nullptr);
88*ec779b8eSAndroid Build Coastguard Worker     createAidlConversion(effect, sessionId, ioId, desc);
89*ec779b8eSAndroid Build Coastguard Worker }
90*ec779b8eSAndroid Build Coastguard Worker 
~EffectHalAidl()91*ec779b8eSAndroid Build Coastguard Worker EffectHalAidl::~EffectHalAidl() {
92*ec779b8eSAndroid Build Coastguard Worker     if (mEffect) {
93*ec779b8eSAndroid Build Coastguard Worker         if (mIsProxyEffect) {
94*ec779b8eSAndroid Build Coastguard Worker             std::static_pointer_cast<EffectProxy>(mEffect)->destroy();
95*ec779b8eSAndroid Build Coastguard Worker         } else if (mFactory) {
96*ec779b8eSAndroid Build Coastguard Worker             mFactory->destroyEffect(mEffect);
97*ec779b8eSAndroid Build Coastguard Worker         }
98*ec779b8eSAndroid Build Coastguard Worker     }
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker 
createAidlConversion(std::shared_ptr<IEffect> effect,int32_t sessionId,int32_t ioId,const Descriptor & desc)101*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::createAidlConversion(
102*ec779b8eSAndroid Build Coastguard Worker         std::shared_ptr<IEffect> effect,
103*ec779b8eSAndroid Build Coastguard Worker         int32_t sessionId, int32_t ioId,
104*ec779b8eSAndroid Build Coastguard Worker         const Descriptor& desc) {
105*ec779b8eSAndroid Build Coastguard Worker     const auto& typeUuid = desc.common.id.type;
106*ec779b8eSAndroid Build Coastguard Worker     ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
107*ec779b8eSAndroid Build Coastguard Worker     if (typeUuid ==
108*ec779b8eSAndroid Build Coastguard Worker         ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
109*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId,
110*ec779b8eSAndroid Build Coastguard Worker                                                                            desc, mIsProxyEffect);
111*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid == ::aidl::android::hardware::audio::effect::
112*ec779b8eSAndroid Build Coastguard Worker                                    getEffectTypeUuidAutomaticGainControlV1()) {
113*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
114*ec779b8eSAndroid Build Coastguard Worker                                                                             desc, mIsProxyEffect);
115*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid == ::aidl::android::hardware::audio::effect::
116*ec779b8eSAndroid Build Coastguard Worker                                    getEffectTypeUuidAutomaticGainControlV2()) {
117*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
118*ec779b8eSAndroid Build Coastguard Worker                                                                             desc, mIsProxyEffect);
119*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
120*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(
121*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
122*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
123*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionDownmix>(
124*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
125*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
126*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
127*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId,
128*ec779b8eSAndroid Build Coastguard Worker                                                                           desc, mIsProxyEffect);
129*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
130*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(
131*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
132*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
133*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId,
134*ec779b8eSAndroid Build Coastguard Worker                                                                           desc, mIsProxyEffect);
135*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
136*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
137*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
138*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
139*ec779b8eSAndroid Build Coastguard Worker         mIsHapticGenerator = true;
140*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
141*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
142*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
143*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
144*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
145*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
146*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
147*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
148*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
149*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
150*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
151*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
152*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
153*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
154*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
155*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
156*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
157*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
158*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
159*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
160*ec779b8eSAndroid Build Coastguard Worker     } else if (typeUuid ==
161*ec779b8eSAndroid Build Coastguard Worker                ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
162*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(
163*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
164*ec779b8eSAndroid Build Coastguard Worker     } else {
165*ec779b8eSAndroid Build Coastguard Worker         // For unknown UUID, use vendor extension implementation
166*ec779b8eSAndroid Build Coastguard Worker         mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
167*ec779b8eSAndroid Build Coastguard Worker                 effect, sessionId, ioId, desc, mIsProxyEffect);
168*ec779b8eSAndroid Build Coastguard Worker     }
169*ec779b8eSAndroid Build Coastguard Worker     mEffectName = mConversion->getDescriptor().common.name;
170*ec779b8eSAndroid Build Coastguard Worker     return OK;
171*ec779b8eSAndroid Build Coastguard Worker }
172*ec779b8eSAndroid Build Coastguard Worker 
setInBuffer(const sp<EffectBufferHalInterface> & buffer)173*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
174*ec779b8eSAndroid Build Coastguard Worker     mInBuffer = buffer;
175*ec779b8eSAndroid Build Coastguard Worker     return OK;
176*ec779b8eSAndroid Build Coastguard Worker }
177*ec779b8eSAndroid Build Coastguard Worker 
setOutBuffer(const sp<EffectBufferHalInterface> & buffer)178*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
179*ec779b8eSAndroid Build Coastguard Worker     mOutBuffer = buffer;
180*ec779b8eSAndroid Build Coastguard Worker     return OK;
181*ec779b8eSAndroid Build Coastguard Worker }
182*ec779b8eSAndroid Build Coastguard Worker 
183*ec779b8eSAndroid Build Coastguard Worker // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
process()184*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::process() {
185*ec779b8eSAndroid Build Coastguard Worker     State state = State::INIT;
186*ec779b8eSAndroid Build Coastguard Worker     if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
187*ec779b8eSAndroid Build Coastguard Worker         (state != State::PROCESSING && state != State::DRAINING)) {
188*ec779b8eSAndroid Build Coastguard Worker         ALOGI("%s skipping process because it's %s", mEffectName.c_str(),
189*ec779b8eSAndroid Build Coastguard Worker               mConversion->isBypassing()
190*ec779b8eSAndroid Build Coastguard Worker                       ? "bypassing"
191*ec779b8eSAndroid Build Coastguard Worker                       : aidl::android::hardware::audio::effect::toString(state).c_str());
192*ec779b8eSAndroid Build Coastguard Worker         return -ENODATA;
193*ec779b8eSAndroid Build Coastguard Worker     }
194*ec779b8eSAndroid Build Coastguard Worker 
195*ec779b8eSAndroid Build Coastguard Worker     const std::shared_ptr<android::hardware::EventFlag> efGroup = mConversion->getEventFlagGroup();
196*ec779b8eSAndroid Build Coastguard Worker     if (!efGroup) {
197*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s invalid efGroup", mEffectName.c_str());
198*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
199*ec779b8eSAndroid Build Coastguard Worker     }
200*ec779b8eSAndroid Build Coastguard Worker 
201*ec779b8eSAndroid Build Coastguard Worker     // reopen if halVersion >= kReopenSupportedVersion and receive kEventFlagDataMqUpdate
202*ec779b8eSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(maybeReopen(efGroup));
203*ec779b8eSAndroid Build Coastguard Worker     const size_t samplesWritten = writeToHalInputFmqAndSignal(efGroup);
204*ec779b8eSAndroid Build Coastguard Worker     if (0 == samplesWritten) {
205*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
206*ec779b8eSAndroid Build Coastguard Worker     }
207*ec779b8eSAndroid Build Coastguard Worker 
208*ec779b8eSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(waitHalStatusFmq(samplesWritten));
209*ec779b8eSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(readFromHalOutputFmq(samplesWritten));
210*ec779b8eSAndroid Build Coastguard Worker     return OK;
211*ec779b8eSAndroid Build Coastguard Worker }
212*ec779b8eSAndroid Build Coastguard Worker 
maybeReopen(const std::shared_ptr<android::hardware::EventFlag> & efGroup) const213*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::maybeReopen(
214*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
215*ec779b8eSAndroid Build Coastguard Worker     if (mHalVersion < kReopenSupportedVersion) {
216*ec779b8eSAndroid Build Coastguard Worker         return OK;
217*ec779b8eSAndroid Build Coastguard Worker     }
218*ec779b8eSAndroid Build Coastguard Worker 
219*ec779b8eSAndroid Build Coastguard Worker     // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
220*ec779b8eSAndroid Build Coastguard Worker     if (uint32_t efState = 0; ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
221*ec779b8eSAndroid Build Coastguard Worker                                                              1 /* ns */, true /* retry */) &&
222*ec779b8eSAndroid Build Coastguard Worker                               efState & kEventFlagDataMqUpdate) {
223*ec779b8eSAndroid Build Coastguard Worker         ALOGD("%s V%d receive dataMQUpdate eventFlag from HAL", mEffectName.c_str(), mHalVersion);
224*ec779b8eSAndroid Build Coastguard Worker         return mConversion->reopen();
225*ec779b8eSAndroid Build Coastguard Worker     }
226*ec779b8eSAndroid Build Coastguard Worker     return OK;
227*ec779b8eSAndroid Build Coastguard Worker }
228*ec779b8eSAndroid Build Coastguard Worker 
writeToHalInputFmqAndSignal(const std::shared_ptr<android::hardware::EventFlag> & efGroup) const229*ec779b8eSAndroid Build Coastguard Worker size_t EffectHalAidl::writeToHalInputFmqAndSignal(
230*ec779b8eSAndroid Build Coastguard Worker         const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
231*ec779b8eSAndroid Build Coastguard Worker     const auto inputQ = mConversion->getInputMQ();
232*ec779b8eSAndroid Build Coastguard Worker     if (!inputQ || !inputQ->isValid()) {
233*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s invalid input FMQ", mEffectName.c_str());
234*ec779b8eSAndroid Build Coastguard Worker         return 0;
235*ec779b8eSAndroid Build Coastguard Worker     }
236*ec779b8eSAndroid Build Coastguard Worker 
237*ec779b8eSAndroid Build Coastguard Worker     const size_t fmqSpaceSamples = inputQ->availableToWrite();
238*ec779b8eSAndroid Build Coastguard Worker     const size_t samplesInBuffer =
239*ec779b8eSAndroid Build Coastguard Worker             mInBuffer->audioBuffer()->frameCount * mConversion->getInputChannelCount();
240*ec779b8eSAndroid Build Coastguard Worker     const size_t samplesToWrite = std::min(fmqSpaceSamples, samplesInBuffer);
241*ec779b8eSAndroid Build Coastguard Worker     if (samplesToWrite == 0) {
242*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s not able to write, samplesInBuffer %zu, fmqSpaceSamples %zu", mEffectName.c_str(),
243*ec779b8eSAndroid Build Coastguard Worker               samplesInBuffer, fmqSpaceSamples);
244*ec779b8eSAndroid Build Coastguard Worker         return 0;
245*ec779b8eSAndroid Build Coastguard Worker     }
246*ec779b8eSAndroid Build Coastguard Worker 
247*ec779b8eSAndroid Build Coastguard Worker     const float* const inputRawBuffer = static_cast<const float*>(mInBuffer->audioBuffer()->f32);
248*ec779b8eSAndroid Build Coastguard Worker     if (!inputQ->write(inputRawBuffer, samplesToWrite)) {
249*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s failed to write %zu samples to inputQ [avail %zu]", mEffectName.c_str(),
250*ec779b8eSAndroid Build Coastguard Worker               samplesToWrite, inputQ->availableToWrite());
251*ec779b8eSAndroid Build Coastguard Worker         return 0;
252*ec779b8eSAndroid Build Coastguard Worker     }
253*ec779b8eSAndroid Build Coastguard Worker 
254*ec779b8eSAndroid Build Coastguard Worker     efGroup->wake(mEventFlagDataMqNotEmpty);
255*ec779b8eSAndroid Build Coastguard Worker     return samplesToWrite;
256*ec779b8eSAndroid Build Coastguard Worker }
257*ec779b8eSAndroid Build Coastguard Worker 
writeHapticGeneratorData(size_t totalSamples,float * const outputRawBuffer,float * const fmqOutputBuffer) const258*ec779b8eSAndroid Build Coastguard Worker void EffectHalAidl::writeHapticGeneratorData(size_t totalSamples, float* const outputRawBuffer,
259*ec779b8eSAndroid Build Coastguard Worker                                              float* const fmqOutputBuffer) const {
260*ec779b8eSAndroid Build Coastguard Worker     const auto audioChNum = mConversion->getAudioChannelCount();
261*ec779b8eSAndroid Build Coastguard Worker     const auto audioSamples =
262*ec779b8eSAndroid Build Coastguard Worker             totalSamples * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
263*ec779b8eSAndroid Build Coastguard Worker 
264*ec779b8eSAndroid Build Coastguard Worker     static constexpr float kHalFloatSampleLimit = 2.0f;
265*ec779b8eSAndroid Build Coastguard Worker     // for HapticGenerator, the input data buffer will be updated
266*ec779b8eSAndroid Build Coastguard Worker     float* const inputRawBuffer = static_cast<float*>(mInBuffer->audioBuffer()->f32);
267*ec779b8eSAndroid Build Coastguard Worker     // accumulate or copy input to output, haptic samples remains all zero
268*ec779b8eSAndroid Build Coastguard Worker     if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
269*ec779b8eSAndroid Build Coastguard Worker         accumulate_float(outputRawBuffer, inputRawBuffer, audioSamples);
270*ec779b8eSAndroid Build Coastguard Worker     } else {
271*ec779b8eSAndroid Build Coastguard Worker         memcpy_to_float_from_float_with_clamping(outputRawBuffer, inputRawBuffer, audioSamples,
272*ec779b8eSAndroid Build Coastguard Worker                                                  kHalFloatSampleLimit);
273*ec779b8eSAndroid Build Coastguard Worker     }
274*ec779b8eSAndroid Build Coastguard Worker     // append the haptic sample at the end of input audio samples
275*ec779b8eSAndroid Build Coastguard Worker     memcpy_to_float_from_float_with_clamping(inputRawBuffer + audioSamples,
276*ec779b8eSAndroid Build Coastguard Worker                                              fmqOutputBuffer + audioSamples,
277*ec779b8eSAndroid Build Coastguard Worker                                              totalSamples - audioSamples, kHalFloatSampleLimit);
278*ec779b8eSAndroid Build Coastguard Worker }
279*ec779b8eSAndroid Build Coastguard Worker 
waitHalStatusFmq(size_t samplesWritten) const280*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::waitHalStatusFmq(size_t samplesWritten) const {
281*ec779b8eSAndroid Build Coastguard Worker     const auto statusQ = mConversion->getStatusMQ();
282*ec779b8eSAndroid Build Coastguard Worker     if (const bool statusValid = statusQ && statusQ->isValid(); !statusValid) {
283*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s statusFMQ %s", mEffectName.c_str(), statusValid ? "valid" : "invalid");
284*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
285*ec779b8eSAndroid Build Coastguard Worker     }
286*ec779b8eSAndroid Build Coastguard Worker 
287*ec779b8eSAndroid Build Coastguard Worker     IEffect::Status retStatus{};
288*ec779b8eSAndroid Build Coastguard Worker     if (!statusQ->readBlocking(&retStatus, 1)) {
289*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s V%d read status from status FMQ failed", mEffectName.c_str(), mHalVersion);
290*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
291*ec779b8eSAndroid Build Coastguard Worker     }
292*ec779b8eSAndroid Build Coastguard Worker     if (retStatus.status != OK || (size_t)retStatus.fmqConsumed != samplesWritten ||
293*ec779b8eSAndroid Build Coastguard Worker         retStatus.fmqProduced == 0) {
294*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s read status failed: %s, FMQ consumed %d (of %zu) produced %d",
295*ec779b8eSAndroid Build Coastguard Worker               mEffectName.c_str(), retStatus.toString().c_str(), retStatus.fmqConsumed,
296*ec779b8eSAndroid Build Coastguard Worker               samplesWritten, retStatus.fmqProduced);
297*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
298*ec779b8eSAndroid Build Coastguard Worker     }
299*ec779b8eSAndroid Build Coastguard Worker 
300*ec779b8eSAndroid Build Coastguard Worker     return OK;
301*ec779b8eSAndroid Build Coastguard Worker }
302*ec779b8eSAndroid Build Coastguard Worker 
readFromHalOutputFmq(size_t samplesWritten) const303*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::readFromHalOutputFmq(size_t samplesWritten) const {
304*ec779b8eSAndroid Build Coastguard Worker     const auto outputQ = mConversion->getOutputMQ();
305*ec779b8eSAndroid Build Coastguard Worker     if (const bool outputValid = outputQ && outputQ->isValid(); !outputValid) {
306*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s outputFMQ %s", mEffectName.c_str(), outputValid ? "valid" : "invalid");
307*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
308*ec779b8eSAndroid Build Coastguard Worker     }
309*ec779b8eSAndroid Build Coastguard Worker 
310*ec779b8eSAndroid Build Coastguard Worker     const size_t fmqProducedSamples = outputQ->availableToRead();
311*ec779b8eSAndroid Build Coastguard Worker     const size_t bufferSpaceSamples =
312*ec779b8eSAndroid Build Coastguard Worker             mOutBuffer->audioBuffer()->frameCount * mConversion->getOutputChannelCount();
313*ec779b8eSAndroid Build Coastguard Worker     const size_t samplesToRead = std::min(fmqProducedSamples, bufferSpaceSamples);
314*ec779b8eSAndroid Build Coastguard Worker     if (samplesToRead == 0) {
315*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s unable to read, bufferSpace %zu, fmqProduced %zu samplesWritten %zu",
316*ec779b8eSAndroid Build Coastguard Worker               mEffectName.c_str(), bufferSpaceSamples, fmqProducedSamples, samplesWritten);
317*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
318*ec779b8eSAndroid Build Coastguard Worker     }
319*ec779b8eSAndroid Build Coastguard Worker 
320*ec779b8eSAndroid Build Coastguard Worker     float* const outputRawBuffer = static_cast<float*>(mOutBuffer->audioBuffer()->f32);
321*ec779b8eSAndroid Build Coastguard Worker     float* fmqOutputBuffer = outputRawBuffer;
322*ec779b8eSAndroid Build Coastguard Worker     std::vector<float> tempBuffer;
323*ec779b8eSAndroid Build Coastguard Worker     // keep original data in the output buffer for accumulate mode or HapticGenerator effect
324*ec779b8eSAndroid Build Coastguard Worker     if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE || mIsHapticGenerator) {
325*ec779b8eSAndroid Build Coastguard Worker         tempBuffer.resize(samplesToRead, 0);
326*ec779b8eSAndroid Build Coastguard Worker         fmqOutputBuffer = tempBuffer.data();
327*ec779b8eSAndroid Build Coastguard Worker     }
328*ec779b8eSAndroid Build Coastguard Worker     // always read floating point data for AIDL
329*ec779b8eSAndroid Build Coastguard Worker     if (!outputQ->read(fmqOutputBuffer, samplesToRead)) {
330*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", mEffectName.c_str(),
331*ec779b8eSAndroid Build Coastguard Worker               samplesToRead, fmqOutputBuffer);
332*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
333*ec779b8eSAndroid Build Coastguard Worker     }
334*ec779b8eSAndroid Build Coastguard Worker 
335*ec779b8eSAndroid Build Coastguard Worker     // HapticGenerator needs special handling because the generated haptic samples should append to
336*ec779b8eSAndroid Build Coastguard Worker     // the end of audio samples, the generated haptic data pass back from HAL in output FMQ at same
337*ec779b8eSAndroid Build Coastguard Worker     // offset as input buffer, here we skip the audio samples in output FMQ and append haptic
338*ec779b8eSAndroid Build Coastguard Worker     // samples to the end of input buffer
339*ec779b8eSAndroid Build Coastguard Worker     if (mIsHapticGenerator) {
340*ec779b8eSAndroid Build Coastguard Worker         assert(samplesRead == samplesWritten);
341*ec779b8eSAndroid Build Coastguard Worker         writeHapticGeneratorData(samplesToRead, outputRawBuffer, fmqOutputBuffer);
342*ec779b8eSAndroid Build Coastguard Worker     } else if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
343*ec779b8eSAndroid Build Coastguard Worker         accumulate_float(outputRawBuffer, fmqOutputBuffer, samplesToRead);
344*ec779b8eSAndroid Build Coastguard Worker     }
345*ec779b8eSAndroid Build Coastguard Worker 
346*ec779b8eSAndroid Build Coastguard Worker     return OK;
347*ec779b8eSAndroid Build Coastguard Worker }
348*ec779b8eSAndroid Build Coastguard Worker 
349*ec779b8eSAndroid Build Coastguard Worker // TODO: no one using, maybe deprecate this interface
processReverse()350*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::processReverse() {
351*ec779b8eSAndroid Build Coastguard Worker     ALOGW("%s not implemented yet", __func__);
352*ec779b8eSAndroid Build Coastguard Worker     return OK;
353*ec779b8eSAndroid Build Coastguard Worker }
354*ec779b8eSAndroid Build Coastguard Worker 
command(uint32_t cmdCode,uint32_t cmdSize,void * pCmdData,uint32_t * replySize,void * pReplyData)355*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
356*ec779b8eSAndroid Build Coastguard Worker                                 uint32_t* replySize, void* pReplyData) {
357*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
358*ec779b8eSAndroid Build Coastguard Worker     if (!mConversion) {
359*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
360*ec779b8eSAndroid Build Coastguard Worker         return INVALID_OPERATION;
361*ec779b8eSAndroid Build Coastguard Worker     }
362*ec779b8eSAndroid Build Coastguard Worker 
363*ec779b8eSAndroid Build Coastguard Worker     return mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
364*ec779b8eSAndroid Build Coastguard Worker }
365*ec779b8eSAndroid Build Coastguard Worker 
getDescriptor(effect_descriptor_t * pDescriptor)366*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
367*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
368*ec779b8eSAndroid Build Coastguard Worker     if (pDescriptor == nullptr) {
369*ec779b8eSAndroid Build Coastguard Worker         ALOGE("%s null descriptor pointer", __func__);
370*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
371*ec779b8eSAndroid Build Coastguard Worker     }
372*ec779b8eSAndroid Build Coastguard Worker     Descriptor aidlDesc;
373*ec779b8eSAndroid Build Coastguard Worker     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getDescriptor(&aidlDesc)));
374*ec779b8eSAndroid Build Coastguard Worker 
375*ec779b8eSAndroid Build Coastguard Worker     *pDescriptor = VALUE_OR_RETURN_STATUS(
376*ec779b8eSAndroid Build Coastguard Worker             ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(aidlDesc));
377*ec779b8eSAndroid Build Coastguard Worker     return OK;
378*ec779b8eSAndroid Build Coastguard Worker }
379*ec779b8eSAndroid Build Coastguard Worker 
close()380*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::close() {
381*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
382*ec779b8eSAndroid Build Coastguard Worker     mEffect->command(CommandId::STOP);
383*ec779b8eSAndroid Build Coastguard Worker     return statusTFromBinderStatus(mEffect->close());
384*ec779b8eSAndroid Build Coastguard Worker }
385*ec779b8eSAndroid Build Coastguard Worker 
dump(int fd)386*ec779b8eSAndroid Build Coastguard Worker status_t EffectHalAidl::dump(int fd) {
387*ec779b8eSAndroid Build Coastguard Worker     TIME_CHECK();
388*ec779b8eSAndroid Build Coastguard Worker     return mEffect->dump(fd, nullptr, 0);
389*ec779b8eSAndroid Build Coastguard Worker }
390*ec779b8eSAndroid Build Coastguard Worker 
391*ec779b8eSAndroid Build Coastguard Worker } // namespace effect
392*ec779b8eSAndroid Build Coastguard Worker } // namespace android
393