1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2023 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 <algorithm>
18*ec779b8eSAndroid Build Coastguard Worker #include <cstddef>
19*ec779b8eSAndroid Build Coastguard Worker #include <iterator>
20*ec779b8eSAndroid Build Coastguard Worker #include <memory>
21*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "EffectProxy"
22*ec779b8eSAndroid Build Coastguard Worker // #define LOG_NDEBUG 0
23*ec779b8eSAndroid Build Coastguard Worker
24*ec779b8eSAndroid Build Coastguard Worker #include <fmq/AidlMessageQueue.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <system/audio_aidl_utils.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <system/audio_effects/aidl_effects_utils.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
28*ec779b8eSAndroid Build Coastguard Worker
29*ec779b8eSAndroid Build Coastguard Worker #include "EffectProxy.h"
30*ec779b8eSAndroid Build Coastguard Worker
31*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::Capability;
32*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::CommandId;
33*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::Descriptor;
34*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::Flags;
35*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::IEffect;
36*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::IFactory;
37*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::Parameter;
38*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::hardware::audio::effect::State;
39*ec779b8eSAndroid Build Coastguard Worker using ::aidl::android::media::audio::common::AudioUuid;
40*ec779b8eSAndroid Build Coastguard Worker
41*ec779b8eSAndroid Build Coastguard Worker namespace android::effect {
42*ec779b8eSAndroid Build Coastguard Worker
EffectProxy(const AudioUuid & uuid,const std::vector<Descriptor> & descriptors,const std::shared_ptr<IFactory> & factory)43*ec779b8eSAndroid Build Coastguard Worker EffectProxy::EffectProxy(const AudioUuid& uuid, const std::vector<Descriptor>& descriptors,
44*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<IFactory>& factory)
45*ec779b8eSAndroid Build Coastguard Worker : mSharedCapability(buildDescriptorCapability(descriptors)),
46*ec779b8eSAndroid Build Coastguard Worker mDescriptorCommon(buildDescriptorCommon(uuid, descriptors)),
47*ec779b8eSAndroid Build Coastguard Worker mSubEffects(
48*ec779b8eSAndroid Build Coastguard Worker [](const std::vector<Descriptor>& descs, const std::shared_ptr<IFactory>& factory) {
49*ec779b8eSAndroid Build Coastguard Worker std::vector<SubEffect> subEffects;
50*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(factory, "invalid EffectFactory handle");
51*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
52*ec779b8eSAndroid Build Coastguard Worker for (const auto& desc : descs) {
53*ec779b8eSAndroid Build Coastguard Worker SubEffect sub({.descriptor = desc});
54*ec779b8eSAndroid Build Coastguard Worker status = factory->createEffect(desc.common.id.uuid, &sub.handle);
55*ec779b8eSAndroid Build Coastguard Worker if (!status.isOk() || !sub.handle) {
56*ec779b8eSAndroid Build Coastguard Worker sub.handle = nullptr;
57*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s create sub-effect %s failed", __func__,
58*ec779b8eSAndroid Build Coastguard Worker ::android::audio::utils::toString(desc.common.id.uuid).c_str());
59*ec779b8eSAndroid Build Coastguard Worker }
60*ec779b8eSAndroid Build Coastguard Worker subEffects.emplace_back(sub);
61*ec779b8eSAndroid Build Coastguard Worker }
62*ec779b8eSAndroid Build Coastguard Worker return subEffects;
63*ec779b8eSAndroid Build Coastguard Worker }(descriptors, factory)),
64*ec779b8eSAndroid Build Coastguard Worker mFactory(factory) {}
65*ec779b8eSAndroid Build Coastguard Worker
~EffectProxy()66*ec779b8eSAndroid Build Coastguard Worker EffectProxy::~EffectProxy() {
67*ec779b8eSAndroid Build Coastguard Worker close();
68*ec779b8eSAndroid Build Coastguard Worker destroy();
69*ec779b8eSAndroid Build Coastguard Worker mSubEffects.clear();
70*ec779b8eSAndroid Build Coastguard Worker }
71*ec779b8eSAndroid Build Coastguard Worker
destroy()72*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::destroy() {
73*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s: %s", __func__,
74*ec779b8eSAndroid Build Coastguard Worker ::android::audio::utils::toString(mDescriptorCommon.id.type).c_str());
75*ec779b8eSAndroid Build Coastguard Worker return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
76*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
77*ec779b8eSAndroid Build Coastguard Worker if (status.isOk()) {
78*ec779b8eSAndroid Build Coastguard Worker effect.reset();
79*ec779b8eSAndroid Build Coastguard Worker }
80*ec779b8eSAndroid Build Coastguard Worker return status;
81*ec779b8eSAndroid Build Coastguard Worker });
82*ec779b8eSAndroid Build Coastguard Worker }
83*ec779b8eSAndroid Build Coastguard Worker
setOffloadParam(const effect_offload_param_t * offload)84*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::setOffloadParam(const effect_offload_param_t* offload) {
85*ec779b8eSAndroid Build Coastguard Worker const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) {
86*ec779b8eSAndroid Build Coastguard Worker const auto& desc = sub.descriptor;
87*ec779b8eSAndroid Build Coastguard Worker return offload->isOffload == desc.common.flags.offloadIndication;
88*ec779b8eSAndroid Build Coastguard Worker });
89*ec779b8eSAndroid Build Coastguard Worker if (itor == mSubEffects.end()) {
90*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s no %soffload sub-effect found", __func__, offload->isOffload ? "" : "non-");
91*ec779b8eSAndroid Build Coastguard Worker mActiveSubIdx = 0;
92*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
93*ec779b8eSAndroid Build Coastguard Worker "noActiveEffctFound");
94*ec779b8eSAndroid Build Coastguard Worker }
95*ec779b8eSAndroid Build Coastguard Worker
96*ec779b8eSAndroid Build Coastguard Worker mActiveSubIdx = std::distance(mSubEffects.begin(), itor);
97*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: active %soffload sub-effect %zu: %s", __func__,
98*ec779b8eSAndroid Build Coastguard Worker offload->isOffload ? "" : "non-", mActiveSubIdx,
99*ec779b8eSAndroid Build Coastguard Worker ::android::audio::utils::toString(mSubEffects[mActiveSubIdx].descriptor.common.id.uuid)
100*ec779b8eSAndroid Build Coastguard Worker .c_str());
101*ec779b8eSAndroid Build Coastguard Worker return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
102*ec779b8eSAndroid Build Coastguard Worker return effect->setParameter(Parameter::make<Parameter::offload>(offload->isOffload));
103*ec779b8eSAndroid Build Coastguard Worker });
104*ec779b8eSAndroid Build Coastguard Worker }
105*ec779b8eSAndroid Build Coastguard Worker
106*ec779b8eSAndroid Build Coastguard Worker // EffectProxy go over sub-effects and call IEffect interfaces
open(const Parameter::Common & common,const std::optional<Parameter::Specific> & specific,IEffect::OpenEffectReturn * ret __unused)107*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
108*ec779b8eSAndroid Build Coastguard Worker const std::optional<Parameter::Specific>& specific,
109*ec779b8eSAndroid Build Coastguard Worker IEffect::OpenEffectReturn* ret __unused) {
110*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus status =
111*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "nullEffectHandle");
112*ec779b8eSAndroid Build Coastguard Worker for (auto& sub : mSubEffects) {
113*ec779b8eSAndroid Build Coastguard Worker IEffect::OpenEffectReturn openReturn;
114*ec779b8eSAndroid Build Coastguard Worker if (!sub.handle || !(status = sub.handle->open(common, specific, &openReturn)).isOk()) {
115*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: failed to open %p UUID %s", __func__, sub.handle.get(),
116*ec779b8eSAndroid Build Coastguard Worker ::android::audio::utils::toString(sub.descriptor.common.id.uuid).c_str());
117*ec779b8eSAndroid Build Coastguard Worker break;
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker sub.effectMq.statusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
120*ec779b8eSAndroid Build Coastguard Worker sub.effectMq.inputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
121*ec779b8eSAndroid Build Coastguard Worker sub.effectMq.outputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
122*ec779b8eSAndroid Build Coastguard Worker }
123*ec779b8eSAndroid Build Coastguard Worker
124*ec779b8eSAndroid Build Coastguard Worker // close all opened effects if failure
125*ec779b8eSAndroid Build Coastguard Worker if (!status.isOk()) {
126*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: closing all sub-effects with error %s", __func__,
127*ec779b8eSAndroid Build Coastguard Worker status.getDescription().c_str());
128*ec779b8eSAndroid Build Coastguard Worker close();
129*ec779b8eSAndroid Build Coastguard Worker }
130*ec779b8eSAndroid Build Coastguard Worker
131*ec779b8eSAndroid Build Coastguard Worker return status;
132*ec779b8eSAndroid Build Coastguard Worker }
133*ec779b8eSAndroid Build Coastguard Worker
reopen(OpenEffectReturn * ret __unused)134*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::reopen(OpenEffectReturn* ret __unused) {
135*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus status =
136*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "nullEffectHandle");
137*ec779b8eSAndroid Build Coastguard Worker for (auto& sub : mSubEffects) {
138*ec779b8eSAndroid Build Coastguard Worker IEffect::OpenEffectReturn openReturn;
139*ec779b8eSAndroid Build Coastguard Worker if (!sub.handle || !(status = sub.handle->reopen(&openReturn)).isOk()) {
140*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: failed to open %p UUID %s", __func__, sub.handle.get(),
141*ec779b8eSAndroid Build Coastguard Worker ::android::audio::utils::toString(sub.descriptor.common.id.uuid).c_str());
142*ec779b8eSAndroid Build Coastguard Worker break;
143*ec779b8eSAndroid Build Coastguard Worker }
144*ec779b8eSAndroid Build Coastguard Worker sub.effectMq.statusQ = std::make_shared<StatusMQ>(openReturn.statusMQ);
145*ec779b8eSAndroid Build Coastguard Worker sub.effectMq.inputQ = std::make_shared<DataMQ>(openReturn.inputDataMQ);
146*ec779b8eSAndroid Build Coastguard Worker sub.effectMq.outputQ = std::make_shared<DataMQ>(openReturn.outputDataMQ);
147*ec779b8eSAndroid Build Coastguard Worker }
148*ec779b8eSAndroid Build Coastguard Worker
149*ec779b8eSAndroid Build Coastguard Worker // close all opened effects if failure
150*ec779b8eSAndroid Build Coastguard Worker if (!status.isOk()) {
151*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s: closing all sub-effects with error %s", __func__,
152*ec779b8eSAndroid Build Coastguard Worker status.getDescription().c_str());
153*ec779b8eSAndroid Build Coastguard Worker close();
154*ec779b8eSAndroid Build Coastguard Worker }
155*ec779b8eSAndroid Build Coastguard Worker
156*ec779b8eSAndroid Build Coastguard Worker return status;
157*ec779b8eSAndroid Build Coastguard Worker }
158*ec779b8eSAndroid Build Coastguard Worker
close()159*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::close() {
160*ec779b8eSAndroid Build Coastguard Worker command(CommandId::STOP);
161*ec779b8eSAndroid Build Coastguard Worker return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
162*ec779b8eSAndroid Build Coastguard Worker return effect->close();
163*ec779b8eSAndroid Build Coastguard Worker });
164*ec779b8eSAndroid Build Coastguard Worker }
165*ec779b8eSAndroid Build Coastguard Worker
getDescriptor(Descriptor * desc)166*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::getDescriptor(Descriptor* desc) {
167*ec779b8eSAndroid Build Coastguard Worker *desc = mSubEffects[mActiveSubIdx].descriptor;
168*ec779b8eSAndroid Build Coastguard Worker desc->capability = mSharedCapability;
169*ec779b8eSAndroid Build Coastguard Worker desc->common = mDescriptorCommon;
170*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
171*ec779b8eSAndroid Build Coastguard Worker }
172*ec779b8eSAndroid Build Coastguard Worker
buildDescriptor(const AudioUuid & uuid,const std::vector<Descriptor> & subEffectDescs,Descriptor * desc)173*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::buildDescriptor(const AudioUuid& uuid,
174*ec779b8eSAndroid Build Coastguard Worker const std::vector<Descriptor>& subEffectDescs,
175*ec779b8eSAndroid Build Coastguard Worker Descriptor* desc) {
176*ec779b8eSAndroid Build Coastguard Worker if (!desc) {
177*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: null descriptor pointer", __func__);
178*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER, "nullptr");
179*ec779b8eSAndroid Build Coastguard Worker }
180*ec779b8eSAndroid Build Coastguard Worker
181*ec779b8eSAndroid Build Coastguard Worker if (subEffectDescs.size() < 2) {
182*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: proxy need at least 2 sub-effects, got %zu", __func__, subEffectDescs.size());
183*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
184*ec779b8eSAndroid Build Coastguard Worker "needMoreSubEffects");
185*ec779b8eSAndroid Build Coastguard Worker }
186*ec779b8eSAndroid Build Coastguard Worker
187*ec779b8eSAndroid Build Coastguard Worker desc->common = buildDescriptorCommon(uuid, subEffectDescs);
188*ec779b8eSAndroid Build Coastguard Worker desc->capability = buildDescriptorCapability(subEffectDescs);
189*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::ok();
190*ec779b8eSAndroid Build Coastguard Worker }
191*ec779b8eSAndroid Build Coastguard Worker
192*ec779b8eSAndroid Build Coastguard Worker // Sub-effects are required to have identical features, so here we return the SW sub-effect
193*ec779b8eSAndroid Build Coastguard Worker // descriptor, with the implementation UUID replaced with proxy UUID, and flags setting respect all
194*ec779b8eSAndroid Build Coastguard Worker // sub-effects.
buildDescriptorCommon(const AudioUuid & uuid,const std::vector<Descriptor> & subEffectDescs)195*ec779b8eSAndroid Build Coastguard Worker Descriptor::Common EffectProxy::buildDescriptorCommon(
196*ec779b8eSAndroid Build Coastguard Worker const AudioUuid& uuid, const std::vector<Descriptor>& subEffectDescs) {
197*ec779b8eSAndroid Build Coastguard Worker Descriptor::Common swCommon;
198*ec779b8eSAndroid Build Coastguard Worker const Flags& firstFlag = subEffectDescs[0].common.flags;
199*ec779b8eSAndroid Build Coastguard Worker bool offloadExist = false;
200*ec779b8eSAndroid Build Coastguard Worker for (const auto& desc : subEffectDescs) {
201*ec779b8eSAndroid Build Coastguard Worker if (desc.common.flags.offloadIndication) {
202*ec779b8eSAndroid Build Coastguard Worker offloadExist = true;
203*ec779b8eSAndroid Build Coastguard Worker } else {
204*ec779b8eSAndroid Build Coastguard Worker swCommon = desc.common;
205*ec779b8eSAndroid Build Coastguard Worker }
206*ec779b8eSAndroid Build Coastguard Worker if (desc.common.flags.audioModeIndication != firstFlag.audioModeIndication ||
207*ec779b8eSAndroid Build Coastguard Worker desc.common.flags.audioSourceIndication != firstFlag.audioSourceIndication ||
208*ec779b8eSAndroid Build Coastguard Worker desc.common.flags.sinkMetadataIndication != firstFlag.sinkMetadataIndication ||
209*ec779b8eSAndroid Build Coastguard Worker desc.common.flags.sourceMetadataIndication != firstFlag.sourceMetadataIndication ||
210*ec779b8eSAndroid Build Coastguard Worker desc.common.flags.deviceIndication != firstFlag.deviceIndication) {
211*ec779b8eSAndroid Build Coastguard Worker ALOGW("Inconsistent flags %s vs %s", desc.common.flags.toString().c_str(),
212*ec779b8eSAndroid Build Coastguard Worker firstFlag.toString().c_str());
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker }
215*ec779b8eSAndroid Build Coastguard Worker
216*ec779b8eSAndroid Build Coastguard Worker swCommon.flags.offloadIndication = offloadExist;
217*ec779b8eSAndroid Build Coastguard Worker // replace implementation UUID with proxy UUID.
218*ec779b8eSAndroid Build Coastguard Worker swCommon.id.uuid = uuid;
219*ec779b8eSAndroid Build Coastguard Worker swCommon.id.proxy = std::nullopt;
220*ec779b8eSAndroid Build Coastguard Worker return swCommon;
221*ec779b8eSAndroid Build Coastguard Worker }
222*ec779b8eSAndroid Build Coastguard Worker
223*ec779b8eSAndroid Build Coastguard Worker // Build a shared Descriptor capability with all sub-effects.
buildDescriptorCapability(const std::vector<Descriptor> & subEffectDescs)224*ec779b8eSAndroid Build Coastguard Worker Capability EffectProxy::buildDescriptorCapability(const std::vector<Descriptor>& subEffectDescs) {
225*ec779b8eSAndroid Build Coastguard Worker std::optional<Capability> cap = subEffectDescs[0].capability;
226*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 1; i < subEffectDescs.size(); i++) {
227*ec779b8eSAndroid Build Coastguard Worker cap = findSharedCapability(cap.value(), subEffectDescs[i].capability);
228*ec779b8eSAndroid Build Coastguard Worker if (!cap) {
229*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s failed to find the shared capability at %zu", __func__, i);
230*ec779b8eSAndroid Build Coastguard Worker return subEffectDescs[0].capability;
231*ec779b8eSAndroid Build Coastguard Worker }
232*ec779b8eSAndroid Build Coastguard Worker }
233*ec779b8eSAndroid Build Coastguard Worker
234*ec779b8eSAndroid Build Coastguard Worker return cap.value();
235*ec779b8eSAndroid Build Coastguard Worker }
236*ec779b8eSAndroid Build Coastguard Worker
237*ec779b8eSAndroid Build Coastguard Worker // Handle with active sub-effect first, only send to other sub-effects when success
command(CommandId id)238*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::command(CommandId id) {
239*ec779b8eSAndroid Build Coastguard Worker return runWithActiveSubEffectThenOthers(
240*ec779b8eSAndroid Build Coastguard Worker [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
241*ec779b8eSAndroid Build Coastguard Worker return effect->command(id);
242*ec779b8eSAndroid Build Coastguard Worker });
243*ec779b8eSAndroid Build Coastguard Worker }
244*ec779b8eSAndroid Build Coastguard Worker
245*ec779b8eSAndroid Build Coastguard Worker // Return the active sub-effect state
getState(State * state)246*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::getState(State* state) {
247*ec779b8eSAndroid Build Coastguard Worker return runWithActiveSubEffect(
248*ec779b8eSAndroid Build Coastguard Worker [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
249*ec779b8eSAndroid Build Coastguard Worker return effect->getState(state);
250*ec779b8eSAndroid Build Coastguard Worker });
251*ec779b8eSAndroid Build Coastguard Worker }
252*ec779b8eSAndroid Build Coastguard Worker
253*ec779b8eSAndroid Build Coastguard Worker // Handle with active sub-effect first, only send to other sub-effects when success
setParameter(const Parameter & param)254*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::setParameter(const Parameter& param) {
255*ec779b8eSAndroid Build Coastguard Worker return runWithActiveSubEffectThenOthers(
256*ec779b8eSAndroid Build Coastguard Worker [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
257*ec779b8eSAndroid Build Coastguard Worker return effect->setParameter(param);
258*ec779b8eSAndroid Build Coastguard Worker });
259*ec779b8eSAndroid Build Coastguard Worker }
260*ec779b8eSAndroid Build Coastguard Worker
261*ec779b8eSAndroid Build Coastguard Worker // Return the active sub-effect parameter
getParameter(const Parameter::Id & id,Parameter * param)262*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::getParameter(const Parameter::Id& id, Parameter* param) {
263*ec779b8eSAndroid Build Coastguard Worker return runWithActiveSubEffect(
264*ec779b8eSAndroid Build Coastguard Worker [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
265*ec779b8eSAndroid Build Coastguard Worker return effect->getParameter(id, param);
266*ec779b8eSAndroid Build Coastguard Worker });
267*ec779b8eSAndroid Build Coastguard Worker }
268*ec779b8eSAndroid Build Coastguard Worker
runWithActiveSubEffectThenOthers(std::function<ndk::ScopedAStatus (const std::shared_ptr<IEffect> &)> const & func)269*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::runWithActiveSubEffectThenOthers(
270*ec779b8eSAndroid Build Coastguard Worker std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
271*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus status = runWithActiveSubEffect(func);
272*ec779b8eSAndroid Build Coastguard Worker if (!status.isOk()) {
273*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s active sub-effect return error %s", __func__, status.getDescription().c_str());
274*ec779b8eSAndroid Build Coastguard Worker }
275*ec779b8eSAndroid Build Coastguard Worker
276*ec779b8eSAndroid Build Coastguard Worker // proceed with others
277*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < mSubEffects.size(); i++) {
278*ec779b8eSAndroid Build Coastguard Worker if (i == mActiveSubIdx) {
279*ec779b8eSAndroid Build Coastguard Worker continue;
280*ec779b8eSAndroid Build Coastguard Worker }
281*ec779b8eSAndroid Build Coastguard Worker if (!mSubEffects[i].handle) {
282*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s null sub-effect interface for %s", __func__,
283*ec779b8eSAndroid Build Coastguard Worker mSubEffects[i].descriptor.common.id.uuid.toString().c_str());
284*ec779b8eSAndroid Build Coastguard Worker continue;
285*ec779b8eSAndroid Build Coastguard Worker }
286*ec779b8eSAndroid Build Coastguard Worker func(mSubEffects[i].handle);
287*ec779b8eSAndroid Build Coastguard Worker }
288*ec779b8eSAndroid Build Coastguard Worker return status;
289*ec779b8eSAndroid Build Coastguard Worker }
290*ec779b8eSAndroid Build Coastguard Worker
runWithActiveSubEffect(std::function<ndk::ScopedAStatus (const std::shared_ptr<IEffect> &)> const & func)291*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::runWithActiveSubEffect(
292*ec779b8eSAndroid Build Coastguard Worker std::function<ndk::ScopedAStatus(const std::shared_ptr<IEffect>&)> const& func) {
293*ec779b8eSAndroid Build Coastguard Worker if (!mSubEffects[mActiveSubIdx].handle) {
294*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s null active sub-effect interface, active %s", __func__,
295*ec779b8eSAndroid Build Coastguard Worker mSubEffects[mActiveSubIdx].descriptor.toString().c_str());
296*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_NULL_POINTER,
297*ec779b8eSAndroid Build Coastguard Worker "activeSubEffectNull");
298*ec779b8eSAndroid Build Coastguard Worker }
299*ec779b8eSAndroid Build Coastguard Worker return func(mSubEffects[mActiveSubIdx].handle);
300*ec779b8eSAndroid Build Coastguard Worker }
301*ec779b8eSAndroid Build Coastguard Worker
runWithAllSubEffects(std::function<ndk::ScopedAStatus (std::shared_ptr<IEffect> &)> const & func)302*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus EffectProxy::runWithAllSubEffects(
303*ec779b8eSAndroid Build Coastguard Worker std::function<ndk::ScopedAStatus(std::shared_ptr<IEffect>&)> const& func) {
304*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
305*ec779b8eSAndroid Build Coastguard Worker // proceed with others if active sub-effect success
306*ec779b8eSAndroid Build Coastguard Worker for (auto& sub : mSubEffects) {
307*ec779b8eSAndroid Build Coastguard Worker if (!sub.handle) {
308*ec779b8eSAndroid Build Coastguard Worker ALOGW("%s null sub-effect interface %s", __func__, sub.descriptor.toString().c_str());
309*ec779b8eSAndroid Build Coastguard Worker continue;
310*ec779b8eSAndroid Build Coastguard Worker }
311*ec779b8eSAndroid Build Coastguard Worker ndk::ScopedAStatus temp = func(sub.handle);
312*ec779b8eSAndroid Build Coastguard Worker if (!temp.isOk()) {
313*ec779b8eSAndroid Build Coastguard Worker status = ndk::ScopedAStatus::fromStatus(temp.getStatus());
314*ec779b8eSAndroid Build Coastguard Worker }
315*ec779b8eSAndroid Build Coastguard Worker }
316*ec779b8eSAndroid Build Coastguard Worker return status;
317*ec779b8eSAndroid Build Coastguard Worker }
318*ec779b8eSAndroid Build Coastguard Worker
isBypassing() const319*ec779b8eSAndroid Build Coastguard Worker bool EffectProxy::isBypassing() const {
320*ec779b8eSAndroid Build Coastguard Worker return mSubEffects[mActiveSubIdx].descriptor.common.flags.bypass;
321*ec779b8eSAndroid Build Coastguard Worker }
322*ec779b8eSAndroid Build Coastguard Worker
isTunnel() const323*ec779b8eSAndroid Build Coastguard Worker bool EffectProxy::isTunnel() const {
324*ec779b8eSAndroid Build Coastguard Worker return mSubEffects[mActiveSubIdx].descriptor.common.flags.hwAcceleratorMode ==
325*ec779b8eSAndroid Build Coastguard Worker Flags::HardwareAccelerator::TUNNEL;
326*ec779b8eSAndroid Build Coastguard Worker }
327*ec779b8eSAndroid Build Coastguard Worker
dump(int fd,const char ** args,uint32_t numArgs)328*ec779b8eSAndroid Build Coastguard Worker binder_status_t EffectProxy::dump(int fd, const char** args, uint32_t numArgs) {
329*ec779b8eSAndroid Build Coastguard Worker const std::string dumpString = toString();
330*ec779b8eSAndroid Build Coastguard Worker write(fd, dumpString.c_str(), dumpString.size());
331*ec779b8eSAndroid Build Coastguard Worker
332*ec779b8eSAndroid Build Coastguard Worker return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
333*ec779b8eSAndroid Build Coastguard Worker return ndk::ScopedAStatus::fromStatus(effect->dump(fd, args, numArgs));
334*ec779b8eSAndroid Build Coastguard Worker })
335*ec779b8eSAndroid Build Coastguard Worker .getStatus();
336*ec779b8eSAndroid Build Coastguard Worker }
337*ec779b8eSAndroid Build Coastguard Worker
toString(size_t level) const338*ec779b8eSAndroid Build Coastguard Worker std::string EffectProxy::toString(size_t level) const {
339*ec779b8eSAndroid Build Coastguard Worker std::string prefixSpace(level, ' ');
340*ec779b8eSAndroid Build Coastguard Worker std::string ss = prefixSpace + "EffectProxy:\n";
341*ec779b8eSAndroid Build Coastguard Worker prefixSpace += " ";
342*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sDescriptorCommon: %s\n", prefixSpace.c_str(),
343*ec779b8eSAndroid Build Coastguard Worker mDescriptorCommon.toString().c_str());
344*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sDescriptorCapability: %s\n", prefixSpace.c_str(),
345*ec779b8eSAndroid Build Coastguard Worker mSharedCapability.toString().c_str());
346*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sActiveSubIdx: %zu\n", prefixSpace.c_str(), mActiveSubIdx);
347*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%sAllSubEffects:\n", prefixSpace.c_str());
348*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < mSubEffects.size(); i++) {
349*ec779b8eSAndroid Build Coastguard Worker base::StringAppendF(&ss, "%s[%zu] - Handle: %p, %s\n", prefixSpace.c_str(), i,
350*ec779b8eSAndroid Build Coastguard Worker mSubEffects[i].handle.get(),
351*ec779b8eSAndroid Build Coastguard Worker mSubEffects[i].descriptor.toString().c_str());
352*ec779b8eSAndroid Build Coastguard Worker }
353*ec779b8eSAndroid Build Coastguard Worker return ss;
354*ec779b8eSAndroid Build Coastguard Worker }
355*ec779b8eSAndroid Build Coastguard Worker
356*ec779b8eSAndroid Build Coastguard Worker } // namespace android::effect
357