blob: f68dd8aa1099f94096edb242883372ff7051ddd6 [file] [log] [blame]
Shunkai Yao51202502022-12-12 06:11:46 +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 Yaoc6308712023-02-22 17:53:04 +000017#include <cstddef>
Shunkai Yao57b93392024-04-26 04:12:21 +000018#include <cstring>
Shunkai Yao51202502022-12-12 06:11:46 +000019#define LOG_TAG "EffectHalAidl"
20//#define LOG_NDEBUG 0
21
Shunkai Yao242521c2023-01-29 18:08:09 +000022#include <memory>
23
Shunkai Yao919b73f2024-03-13 00:52:08 +000024#include <audio_utils/primitives.h>
Mikhail Naganov5e406ba2023-01-13 00:27:22 +000025#include <error/expected_utils.h>
Shunkai Yao51202502022-12-12 06:11:46 +000026#include <media/AidlConversionCppNdk.h>
Shunkai Yaoa03533e2023-01-25 06:38:10 +000027#include <media/AidlConversionEffect.h>
Mikhail Naganov5e406ba2023-01-13 00:27:22 +000028#include <media/AidlConversionUtil.h>
Shunkai Yao51202502022-12-12 06:11:46 +000029#include <media/EffectsFactoryApi.h>
30#include <mediautils/TimeCheck.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000031#include <system/audio.h>
Shunkai Yao399be682023-03-06 18:54:18 +000032#include <system/audio_effects/effect_uuid.h>
Shunkai Yao51202502022-12-12 06:11:46 +000033#include <utils/Log.h>
34
35#include "EffectHalAidl.h"
Shunkai Yao5c718342023-02-23 23:49:51 +000036#include "EffectProxy.h"
Shunkai Yao51202502022-12-12 06:11:46 +000037
Shunkai Yao51202502022-12-12 06:11:46 +000038#include <aidl/android/hardware/audio/effect/IEffect.h>
39
Shunkai Yaodba8ba32023-01-27 17:02:21 +000040#include "effectsAidlConversion/AidlConversionAec.h"
Shunkai Yao61ce9572023-02-28 23:55:33 +000041#include "effectsAidlConversion/AidlConversionAgc1.h"
Shunkai Yaodba8ba32023-01-27 17:02:21 +000042#include "effectsAidlConversion/AidlConversionAgc2.h"
43#include "effectsAidlConversion/AidlConversionBassBoost.h"
44#include "effectsAidlConversion/AidlConversionDownmix.h"
45#include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
Shunkai Yao242521c2023-01-29 18:08:09 +000046#include "effectsAidlConversion/AidlConversionEnvReverb.h"
47#include "effectsAidlConversion/AidlConversionEq.h"
48#include "effectsAidlConversion/AidlConversionHapticGenerator.h"
49#include "effectsAidlConversion/AidlConversionLoudnessEnhancer.h"
50#include "effectsAidlConversion/AidlConversionNoiseSuppression.h"
51#include "effectsAidlConversion/AidlConversionPresetReverb.h"
52#include "effectsAidlConversion/AidlConversionSpatializer.h"
53#include "effectsAidlConversion/AidlConversionVendorExtension.h"
54#include "effectsAidlConversion/AidlConversionVirtualizer.h"
55#include "effectsAidlConversion/AidlConversionVisualizer.h"
Shunkai Yaodba8ba32023-01-27 17:02:21 +000056
Mikhail Naganov5e406ba2023-01-13 00:27:22 +000057using ::aidl::android::aidl_utils::statusTFromBinderStatus;
David Lia6913432024-02-20 09:54:14 +080058using ::aidl::android::hardware::audio::effect::CommandId;
Shunkai Yao51202502022-12-12 06:11:46 +000059using ::aidl::android::hardware::audio::effect::Descriptor;
60using ::aidl::android::hardware::audio::effect::IEffect;
Shunkai Yao44bdbad2023-01-14 05:11:58 +000061using ::aidl::android::hardware::audio::effect::IFactory;
Shunkai Yaoe910bfd2024-04-18 04:36:42 +000062using ::aidl::android::hardware::audio::effect::kEventFlagDataMqNotEmpty;
Shunkai Yao1afb46c2024-01-09 20:40:45 +000063using ::aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate;
Shunkai Yaoe910bfd2024-04-18 04:36:42 +000064using ::aidl::android::hardware::audio::effect::kEventFlagNotEmpty;
Shunkai Yaoe317e332024-02-06 00:39:49 +000065using ::aidl::android::hardware::audio::effect::kReopenSupportedVersion;
Shunkai Yao26689d92023-08-01 23:06:13 +000066using ::aidl::android::hardware::audio::effect::State;
Shunkai Yao51202502022-12-12 06:11:46 +000067
68namespace android {
69namespace effect {
70
Shunkai Yao399be682023-03-06 18:54:18 +000071EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
Shunkai Yaoe317e332024-02-06 00:39:49 +000072 const std::shared_ptr<IEffect>& effect, int32_t sessionId,
73 int32_t ioId, const Descriptor& desc, bool isProxyEffect)
Shunkai Yaodba8ba32023-01-27 17:02:21 +000074 : mFactory(factory),
Shunkai Yao44bdbad2023-01-14 05:11:58 +000075 mEffect(effect),
Shunkai Yao284bb0d2023-01-10 00:42:36 +000076 mSessionId(sessionId),
77 mIoId(ioId),
Shunkai Yao688613e2024-09-12 23:57:55 +000078 mIsProxyEffect(isProxyEffect),
79 mHalVersion([factory]() {
80 int version = 0;
81 // use factory HAL version because effect can be an EffectProxy instance
82 return factory->getInterfaceVersion(&version).isOk() ? version : 0;
83 }()) {
Shunkai Yaoe317e332024-02-06 00:39:49 +000084 assert(mFactory != nullptr);
85 assert(mEffect != nullptr);
Shunkai Yaodba8ba32023-01-27 17:02:21 +000086 createAidlConversion(effect, sessionId, ioId, desc);
87}
Shunkai Yao51202502022-12-12 06:11:46 +000088
Shunkai Yao44bdbad2023-01-14 05:11:58 +000089EffectHalAidl::~EffectHalAidl() {
Shunkai Yao5c718342023-02-23 23:49:51 +000090 if (mEffect) {
Shunkai Yao79f98742023-05-03 23:54:43 +000091 if (mIsProxyEffect) {
92 std::static_pointer_cast<EffectProxy>(mEffect)->destroy();
93 } else if (mFactory) {
94 mFactory->destroyEffect(mEffect);
95 }
Shunkai Yao44bdbad2023-01-14 05:11:58 +000096 }
97}
Shunkai Yao51202502022-12-12 06:11:46 +000098
Shunkai Yaodba8ba32023-01-27 17:02:21 +000099status_t EffectHalAidl::createAidlConversion(
Shunkai Yao399be682023-03-06 18:54:18 +0000100 std::shared_ptr<IEffect> effect,
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000101 int32_t sessionId, int32_t ioId,
Shunkai Yao399be682023-03-06 18:54:18 +0000102 const Descriptor& desc) {
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000103 const auto& typeUuid = desc.common.id.type;
Shunkai Yao242521c2023-01-29 18:08:09 +0000104 ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
Shunkai Yao399be682023-03-06 18:54:18 +0000105 if (typeUuid ==
106 ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000107 mConversion = std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId,
108 desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000109 } else if (typeUuid == ::aidl::android::hardware::audio::effect::
110 getEffectTypeUuidAutomaticGainControlV1()) {
Shunkai Yao61ce9572023-02-28 23:55:33 +0000111 mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
Shunkai Yao323273d2023-05-24 00:45:43 +0000112 desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000113 } else if (typeUuid == ::aidl::android::hardware::audio::effect::
114 getEffectTypeUuidAutomaticGainControlV2()) {
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000115 mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
Shunkai Yao323273d2023-05-24 00:45:43 +0000116 desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000117 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000118 mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(
119 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000120 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000121 mConversion = std::make_unique<android::effect::AidlConversionDownmix>(
122 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000123 } else if (typeUuid ==
124 ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000125 mConversion = std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId,
126 desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000127 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000128 mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(
129 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000130 } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000131 mConversion = std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId,
132 desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000133 } else if (typeUuid ==
134 ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000135 mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000136 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao57b93392024-04-26 04:12:21 +0000137 mIsHapticGenerator = true;
Shunkai Yao399be682023-03-06 18:54:18 +0000138 } else if (typeUuid ==
139 ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000140 mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000141 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000142 } else if (typeUuid ==
143 ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000144 mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000145 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000146 } else if (typeUuid ==
147 ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000148 mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000149 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000150 } else if (typeUuid ==
151 ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000152 mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000153 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000154 } else if (typeUuid ==
155 ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000156 mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000157 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yao399be682023-03-06 18:54:18 +0000158 } else if (typeUuid ==
159 ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
Shunkai Yao323273d2023-05-24 00:45:43 +0000160 mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(
161 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000162 } else {
Shunkai Yao242521c2023-01-29 18:08:09 +0000163 // For unknown UUID, use vendor extension implementation
164 mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
Shunkai Yao323273d2023-05-24 00:45:43 +0000165 effect, sessionId, ioId, desc, mIsProxyEffect);
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000166 }
Shunkai Yao688613e2024-09-12 23:57:55 +0000167 mEffectName = mConversion->getDescriptor().common.name;
Shunkai Yaodba8ba32023-01-27 17:02:21 +0000168 return OK;
169}
170
Shunkai Yao51202502022-12-12 06:11:46 +0000171status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000172 mInBuffer = buffer;
Shunkai Yao51202502022-12-12 06:11:46 +0000173 return OK;
174}
175
176status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000177 mOutBuffer = buffer;
Shunkai Yao51202502022-12-12 06:11:46 +0000178 return OK;
179}
180
Shunkai Yaoc6308712023-02-22 17:53:04 +0000181// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
Shunkai Yao51202502022-12-12 06:11:46 +0000182status_t EffectHalAidl::process() {
Shunkai Yao26689d92023-08-01 23:06:13 +0000183 State state = State::INIT;
184 if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
185 state != State::PROCESSING) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000186 ALOGI("%s skipping process because it's %s", mEffectName.c_str(),
Shunkai Yao26689d92023-08-01 23:06:13 +0000187 mConversion->isBypassing()
188 ? "bypassing"
189 : aidl::android::hardware::audio::effect::toString(state).c_str());
Jaideep Sharmabd9b0d32023-09-20 11:50:25 +0530190 return -ENODATA;
Shunkai Yao26689d92023-08-01 23:06:13 +0000191 }
192
Shunkai Yao688613e2024-09-12 23:57:55 +0000193 const std::shared_ptr<android::hardware::EventFlag> efGroup = mConversion->getEventFlagGroup();
Shunkai Yao1afb46c2024-01-09 20:40:45 +0000194 if (!efGroup) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000195 ALOGE("%s invalid efGroup", mEffectName.c_str());
Shunkai Yao1afb46c2024-01-09 20:40:45 +0000196 return INVALID_OPERATION;
197 }
198
Shunkai Yao688613e2024-09-12 23:57:55 +0000199 // reopen if halVersion >= kReopenSupportedVersion and receive kEventFlagDataMqUpdate
200 RETURN_STATUS_IF_ERROR(maybeReopen(efGroup));
201 const size_t samplesWritten = writeToHalInputFmqAndSignal(efGroup);
202 if (0 == samplesWritten) {
203 return INVALID_OPERATION;
204 }
Shunkai Yaoe317e332024-02-06 00:39:49 +0000205
Shunkai Yao688613e2024-09-12 23:57:55 +0000206 RETURN_STATUS_IF_ERROR(waitHalStatusFmq(samplesWritten));
207 RETURN_STATUS_IF_ERROR(readFromHalOutputFmq(samplesWritten));
208 return OK;
209}
210
211status_t EffectHalAidl::maybeReopen(
212 const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
213 if (mHalVersion < kReopenSupportedVersion) {
214 return OK;
215 }
216
217 // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
218 if (uint32_t efState = 0; ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
Shunkai Yaoe317e332024-02-06 00:39:49 +0000219 1 /* ns */, true /* retry */) &&
220 efState & kEventFlagDataMqUpdate) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000221 ALOGD("%s V%d receive dataMQUpdate eventFlag from HAL", mEffectName.c_str(), mHalVersion);
222 return mConversion->reopen();
Shunkai Yao1afb46c2024-01-09 20:40:45 +0000223 }
Shunkai Yao688613e2024-09-12 23:57:55 +0000224 return OK;
225}
226
227size_t EffectHalAidl::writeToHalInputFmqAndSignal(
228 const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
229 const auto inputQ = mConversion->getInputMQ();
230 if (!inputQ || !inputQ->isValid()) {
231 ALOGE("%s invalid input FMQ", mEffectName.c_str());
232 return 0;
Shunkai Yao5c718342023-02-23 23:49:51 +0000233 }
234
Shunkai Yao688613e2024-09-12 23:57:55 +0000235 const size_t fmqSpaceSamples = inputQ->availableToWrite();
236 const size_t samplesInBuffer =
237 mInBuffer->audioBuffer()->frameCount * mConversion->getInputChannelCount();
238 const size_t samplesToWrite = std::min(fmqSpaceSamples, samplesInBuffer);
239 if (samplesToWrite == 0) {
240 ALOGE("%s not able to write, samplesInBuffer %zu, fmqSpaceSamples %zu", mEffectName.c_str(),
241 samplesInBuffer, fmqSpaceSamples);
242 return 0;
Shunkai Yaoc6308712023-02-22 17:53:04 +0000243 }
Shunkai Yao688613e2024-09-12 23:57:55 +0000244
245 const float* const inputRawBuffer = static_cast<const float*>(mInBuffer->audioBuffer()->f32);
246 if (!inputQ->write(inputRawBuffer, samplesToWrite)) {
247 ALOGE("%s failed to write %zu samples to inputQ [avail %zu]", mEffectName.c_str(),
248 samplesToWrite, inputQ->availableToWrite());
249 return 0;
Shunkai Yaoc6308712023-02-22 17:53:04 +0000250 }
Shunkai Yaoe910bfd2024-04-18 04:36:42 +0000251
252 // for V2 audio effect HAL, expect different EventFlag to avoid bit conflict with FMQ_NOT_EMPTY
Shunkai Yao688613e2024-09-12 23:57:55 +0000253 efGroup->wake(mHalVersion >= kReopenSupportedVersion ? kEventFlagDataMqNotEmpty
254 : kEventFlagNotEmpty);
255 return samplesToWrite;
256}
257
258void EffectHalAidl::writeHapticGeneratorData(size_t totalSamples, float* const outputRawBuffer,
259 float* const fmqOutputBuffer) const {
260 const auto audioChNum = mConversion->getAudioChannelCount();
261 const auto audioSamples =
262 totalSamples * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
263
264 static constexpr float kHalFloatSampleLimit = 2.0f;
265 // for HapticGenerator, the input data buffer will be updated
266 float* const inputRawBuffer = static_cast<float*>(mInBuffer->audioBuffer()->f32);
267 // accumulate or copy input to output, haptic samples remains all zero
268 if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
269 accumulate_float(outputRawBuffer, inputRawBuffer, audioSamples);
270 } else {
271 memcpy_to_float_from_float_with_clamping(outputRawBuffer, inputRawBuffer, audioSamples,
272 kHalFloatSampleLimit);
273 }
274 // append the haptic sample at the end of input audio samples
275 memcpy_to_float_from_float_with_clamping(inputRawBuffer + audioSamples,
276 fmqOutputBuffer + audioSamples,
277 totalSamples - audioSamples, kHalFloatSampleLimit);
278}
279
280status_t EffectHalAidl::waitHalStatusFmq(size_t samplesWritten) const {
281 const auto statusQ = mConversion->getStatusMQ();
282 if (const bool statusValid = statusQ && statusQ->isValid(); !statusValid) {
283 ALOGE("%s statusFMQ %s", mEffectName.c_str(), statusValid ? "valid" : "invalid");
284 return INVALID_OPERATION;
285 }
Shunkai Yaoc6308712023-02-22 17:53:04 +0000286
287 IEffect::Status retStatus{};
Shunkai Yaoe910bfd2024-04-18 04:36:42 +0000288 if (!statusQ->readBlocking(&retStatus, 1)) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000289 ALOGE("%s V%d read status from status FMQ failed", mEffectName.c_str(), mHalVersion);
Shunkai Yaoe910bfd2024-04-18 04:36:42 +0000290 return INVALID_OPERATION;
291 }
Shunkai Yao688613e2024-09-12 23:57:55 +0000292 if (retStatus.status != OK || (size_t)retStatus.fmqConsumed != samplesWritten ||
Shunkai Yaoe910bfd2024-04-18 04:36:42 +0000293 retStatus.fmqProduced == 0) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000294 ALOGE("%s read status failed: %s, FMQ consumed %d (of %zu) produced %d",
295 mEffectName.c_str(), retStatus.toString().c_str(), retStatus.fmqConsumed,
296 samplesWritten, retStatus.fmqProduced);
Shunkai Yaoc6308712023-02-22 17:53:04 +0000297 return INVALID_OPERATION;
298 }
299
Shunkai Yao688613e2024-09-12 23:57:55 +0000300 return OK;
301}
302
303status_t EffectHalAidl::readFromHalOutputFmq(size_t samplesWritten) const {
304 const auto outputQ = mConversion->getOutputMQ();
305 if (const bool outputValid = outputQ && outputQ->isValid(); !outputValid) {
306 ALOGE("%s outputFMQ %s", mEffectName.c_str(), outputValid ? "valid" : "invalid");
Shunkai Yaoc6308712023-02-22 17:53:04 +0000307 return INVALID_OPERATION;
308 }
Shunkai Yao919b73f2024-03-13 00:52:08 +0000309
Shunkai Yao688613e2024-09-12 23:57:55 +0000310 const size_t fmqProducedSamples = outputQ->availableToRead();
311 const size_t bufferSpaceSamples =
312 mOutBuffer->audioBuffer()->frameCount * mConversion->getOutputChannelCount();
313 const size_t samplesToRead = std::min(fmqProducedSamples, bufferSpaceSamples);
314 if (samplesToRead == 0) {
315 ALOGE("%s unable to read, bufferSpace %zu, fmqProduced %zu samplesWritten %zu",
316 mEffectName.c_str(), bufferSpaceSamples, fmqProducedSamples, samplesWritten);
317 return INVALID_OPERATION;
318 }
319
320 float* const outputRawBuffer = static_cast<float*>(mOutBuffer->audioBuffer()->f32);
321 float* fmqOutputBuffer = outputRawBuffer;
Shunkai Yao919b73f2024-03-13 00:52:08 +0000322 std::vector<float> tempBuffer;
Shunkai Yao57b93392024-04-26 04:12:21 +0000323 // keep original data in the output buffer for accumulate mode or HapticGenerator effect
324 if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE || mIsHapticGenerator) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000325 tempBuffer.resize(samplesToRead, 0);
326 fmqOutputBuffer = tempBuffer.data();
Shunkai Yao919b73f2024-03-13 00:52:08 +0000327 }
Shunkai Yao5c718342023-02-23 23:49:51 +0000328 // always read floating point data for AIDL
Shunkai Yao688613e2024-09-12 23:57:55 +0000329 if (!outputQ->read(fmqOutputBuffer, samplesToRead)) {
330 ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", mEffectName.c_str(),
331 samplesToRead, fmqOutputBuffer);
Shunkai Yaoc6308712023-02-22 17:53:04 +0000332 return INVALID_OPERATION;
333 }
Shunkai Yao57b93392024-04-26 04:12:21 +0000334
335 // HapticGenerator needs special handling because the generated haptic samples should append to
336 // the end of audio samples, the generated haptic data pass back from HAL in output FMQ at same
337 // offset as input buffer, here we skip the audio samples in output FMQ and append haptic
338 // samples to the end of input buffer
339 if (mIsHapticGenerator) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000340 assert(samplesRead == samplesWritten);
341 writeHapticGeneratorData(samplesToRead, outputRawBuffer, fmqOutputBuffer);
Shunkai Yao57b93392024-04-26 04:12:21 +0000342 } else if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
Shunkai Yao688613e2024-09-12 23:57:55 +0000343 accumulate_float(outputRawBuffer, fmqOutputBuffer, samplesToRead);
Shunkai Yao919b73f2024-03-13 00:52:08 +0000344 }
Shunkai Yaoc6308712023-02-22 17:53:04 +0000345
Shunkai Yao51202502022-12-12 06:11:46 +0000346 return OK;
347}
348
349// TODO: no one using, maybe deprecate this interface
350status_t EffectHalAidl::processReverse() {
351 ALOGW("%s not implemented yet", __func__);
352 return OK;
353}
354
Shunkai Yao51202502022-12-12 06:11:46 +0000355status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
356 uint32_t* replySize, void* pReplyData) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000357 TIME_CHECK();
358 if (!mConversion) {
359 ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
360 return INVALID_OPERATION;
361 }
362
Shunkai Yao5c718342023-02-23 23:49:51 +0000363 return mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
Shunkai Yao51202502022-12-12 06:11:46 +0000364}
365
366status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000367 TIME_CHECK();
Shunkai Yao51202502022-12-12 06:11:46 +0000368 if (pDescriptor == nullptr) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000369 ALOGE("%s null descriptor pointer", __func__);
Shunkai Yao51202502022-12-12 06:11:46 +0000370 return BAD_VALUE;
371 }
372 Descriptor aidlDesc;
Mikhail Naganov5e406ba2023-01-13 00:27:22 +0000373 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getDescriptor(&aidlDesc)));
Shunkai Yao51202502022-12-12 06:11:46 +0000374
375 *pDescriptor = VALUE_OR_RETURN_STATUS(
376 ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(aidlDesc));
377 return OK;
378}
379
380status_t EffectHalAidl::close() {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000381 TIME_CHECK();
David Lia6913432024-02-20 09:54:14 +0800382 mEffect->command(CommandId::STOP);
Shunkai Yao44bdbad2023-01-14 05:11:58 +0000383 return statusTFromBinderStatus(mEffect->close());
Shunkai Yao51202502022-12-12 06:11:46 +0000384}
385
386status_t EffectHalAidl::dump(int fd) {
Shunkai Yaoc6308712023-02-22 17:53:04 +0000387 TIME_CHECK();
388 return mEffect->dump(fd, nullptr, 0);
Shunkai Yao51202502022-12-12 06:11:46 +0000389}
390
391} // namespace effect
392} // namespace android