1 /*
2  * Copyright (C) 2023 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 <cstdint>
18 #include <cstring>
19 #include <optional>
20 #define LOG_TAG "AidlConversionDp"
21 //#define LOG_NDEBUG 0
22 
23 #include <error/expected_utils.h>
24 #include <media/AidlConversionCppNdk.h>
25 #include <media/AidlConversionNdk.h>
26 #include <media/AidlConversionEffect.h>
27 #include <system/audio_effect.h>
28 #include <system/audio_effects/aidl_effects_utils.h>
29 #include <system/audio_effects/effect_dynamicsprocessing.h>
30 #include <Utils.h>
31 #include <utils/Log.h>
32 
33 #include "AidlConversionDynamicsProcessing.h"
34 
35 namespace android {
36 namespace effect {
37 
38 using ::aidl::android::convertIntegral;
39 using ::aidl::android::getParameterSpecificField;
40 using ::aidl::android::aidl_utils::statusTFromBinderStatus;
41 using ::aidl::android::hardware::audio::effect::Capability;
42 using ::aidl::android::hardware::audio::effect::clampParameter;
43 using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
44 using ::aidl::android::hardware::audio::effect::Parameter;
45 using ::aidl::android::hardware::audio::effect::Range;
46 using ::aidl::android::hardware::audio::effect::toString;
47 using ::aidl::android::hardware::audio::effect::VendorExtension;
48 using ::android::status_t;
49 using utils::EffectParamReader;
50 using utils::EffectParamWriter;
51 
setParameter(EffectParamReader & param)52 status_t AidlConversionDp::setParameter(EffectParamReader& param) {
53     uint32_t type = 0;
54     RETURN_STATUS_IF_ERROR(param.readFromParameter(&type));
55     Parameter aidlParam;
56     switch (type) {
57         case DP_PARAM_INPUT_GAIN: {
58             DynamicsProcessing::InputGain inputGainAidl;
59             RETURN_STATUS_IF_ERROR(param.readFromParameter(&inputGainAidl.channel));
60             RETURN_STATUS_IF_ERROR(param.readFromValue(&inputGainAidl.gainDb));
61             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, inputGain,
62                                                 {inputGainAidl});
63             break;
64         }
65         case DP_PARAM_ENGINE_ARCHITECTURE: {
66             DynamicsProcessing::EngineArchitecture engine =
67                     VALUE_OR_RETURN_STATUS(readEngineArchitectureFromParam(param));
68             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing,
69                                                 engineArchitecture, engine);
70             mEngine = engine;
71             break;
72         }
73         case DP_PARAM_PRE_EQ: {
74             DynamicsProcessing::ChannelConfig chConfig =
75                     VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
76             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEq,
77                                                 {chConfig});
78             break;
79         }
80         case DP_PARAM_POST_EQ: {
81             DynamicsProcessing::ChannelConfig chConfig =
82                     VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
83             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEq,
84                                                 {chConfig});
85             break;
86         }
87         case DP_PARAM_MBC: {
88             DynamicsProcessing::ChannelConfig chConfig =
89                     VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
90             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbc,
91                                                 {chConfig});
92             break;
93         }
94         case DP_PARAM_PRE_EQ_BAND: {
95             DynamicsProcessing::EqBandConfig bandConfig =
96                     VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
97             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEqBand,
98                                                 {bandConfig});
99             break;
100         }
101         case DP_PARAM_POST_EQ_BAND: {
102             DynamicsProcessing::EqBandConfig bandConfig =
103                     VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
104             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEqBand,
105                                                 {bandConfig});
106             break;
107         }
108         case DP_PARAM_MBC_BAND: {
109             DynamicsProcessing::MbcBandConfig bandConfig =
110                     VALUE_OR_RETURN_STATUS(readMbcBandConfigFromParam(param));
111             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbcBand,
112                                                 {bandConfig});
113             break;
114         }
115         case DP_PARAM_LIMITER: {
116             DynamicsProcessing::LimiterConfig config =
117                     VALUE_OR_RETURN_STATUS(readLimiterConfigFromParam(param));
118             aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, limiter,
119                                                 {config});
120             break;
121         }
122         default: {
123             // for vendor extension, copy data area to the DefaultExtension, parameter ignored
124             VendorExtension ext = VALUE_OR_RETURN_STATUS(
125                     aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param));
126             aidlParam =
127                     MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, vendor, ext);
128             break;
129         }
130     }
131 
132     std::optional<Parameter> clamped =
133             clampParameter<Range::dynamicsProcessing, Parameter::Specific::dynamicsProcessing>(
134                     aidlParam, getDescriptor().capability);
135     if (!clamped) {
136         ALOGE("%s failed to clamp parameters: %s", __func__, aidlParam.toString().c_str());
137         return BAD_VALUE;
138     }
139     return statusTFromBinderStatus(mEffect->setParameter(clamped.value()));
140 }
141 
getParameter(EffectParamWriter & param)142 status_t AidlConversionDp::getParameter(EffectParamWriter& param) {
143     uint32_t type = 0;
144     RETURN_STATUS_IF_ERROR(param.readFromParameter(&type));
145     Parameter aidlParam;
146     switch (type) {
147         case DP_PARAM_INPUT_GAIN: {
148             int32_t channel;
149             RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
150             Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
151                                                           DynamicsProcessing::inputGain);
152             RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
153 
154             std::vector<DynamicsProcessing::InputGain> gains =
155                     VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
156                             aidlParam, DynamicsProcessing, dynamicsProcessing,
157                             DynamicsProcessing::inputGain,
158                             std::vector<DynamicsProcessing::InputGain>));
159             for (const auto& gain : gains) {
160                 if (gain.channel == channel) {
161                     return param.writeToValue(&gain.gainDb);
162                 }
163             }
164             ALOGE("%s not able to find channel %d", __func__, channel);
165             return BAD_VALUE;
166         }
167         case DP_PARAM_ENGINE_ARCHITECTURE: {
168             Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
169                                                           DynamicsProcessing::engineArchitecture);
170             RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
171 
172             DynamicsProcessing::EngineArchitecture engine =
173                     VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
174                             aidlParam, DynamicsProcessing, dynamicsProcessing,
175                             DynamicsProcessing::engineArchitecture,
176                             DynamicsProcessing::EngineArchitecture));
177             int32_t resolution = VALUE_OR_RETURN_STATUS(
178                     aidl::android::aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
179                             engine.resolutionPreference));
180             int32_t preEqInUse =
181                     VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.preEqStage.inUse));
182             int32_t mbcInUse =
183                     VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.mbcStage.inUse));
184             int32_t postEqInUse =
185                     VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.postEqStage.inUse));
186             int32_t limiterInUse =
187                     VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.limiterInUse));
188             RETURN_STATUS_IF_ERROR(param.writeToValue(&resolution));
189             RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.preferredProcessingDurationMs));
190             RETURN_STATUS_IF_ERROR(param.writeToValue(&preEqInUse));
191             RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.preEqStage.bandCount));
192             RETURN_STATUS_IF_ERROR(param.writeToValue(&mbcInUse));
193             RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.mbcStage.bandCount));
194             RETURN_STATUS_IF_ERROR(param.writeToValue(&postEqInUse));
195             RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.postEqStage.bandCount));
196             RETURN_STATUS_IF_ERROR(param.writeToValue(&limiterInUse));
197             mEngine = engine;
198             return OK;
199         }
200         case DP_PARAM_PRE_EQ: {
201             return getChannelConfig(DynamicsProcessing::preEq, param);
202         }
203         case DP_PARAM_POST_EQ: {
204             return getChannelConfig(DynamicsProcessing::postEq, param);
205         }
206         case DP_PARAM_MBC: {
207             return getChannelConfig(DynamicsProcessing::mbc, param);
208         }
209         case DP_PARAM_PRE_EQ_BAND: {
210             return getEqBandConfig(DynamicsProcessing::preEqBand, param);
211         }
212         case DP_PARAM_POST_EQ_BAND: {
213             return getEqBandConfig(DynamicsProcessing::postEqBand, param);
214         }
215         case DP_PARAM_MBC_BAND: {
216             return getMbcBandConfig(param);
217         }
218         case DP_PARAM_LIMITER: {
219             return getLimiterConfig(param);
220         }
221         case DP_PARAM_GET_CHANNEL_COUNT: {
222             uint32_t channel = ::aidl::android::hardware::audio::common::getChannelCount(
223                     mCommon.input.base.channelMask);
224             RETURN_STATUS_IF_ERROR(param.writeToValue(&channel));
225             return OK;
226         }
227         default: {
228             VENDOR_EXTENSION_GET_AND_RETURN(DynamicsProcessing, dynamicsProcessing, param);
229         }
230     }
231 }
232 
233 ConversionResult<DynamicsProcessing::ChannelConfig>
readChannelConfigFromParam(EffectParamReader & param)234 AidlConversionDp::readChannelConfigFromParam(EffectParamReader& param) {
235     int32_t enable, channel;
236     RETURN_IF_ERROR(param.readFromParameter(&channel));
237     RETURN_IF_ERROR(param.readFromValue(&enable));
238 
239     return DynamicsProcessing::ChannelConfig(
240             {.channel = channel, .enable = VALUE_OR_RETURN(convertIntegral<bool>(enable))});
241 }
242 
243 ConversionResult<DynamicsProcessing::EqBandConfig>
readEqBandConfigFromParam(EffectParamReader & param)244 AidlConversionDp::readEqBandConfigFromParam(EffectParamReader& param) {
245     DynamicsProcessing::EqBandConfig config;
246     int32_t enable;
247     RETURN_IF_ERROR(param.readFromParameter(&config.channel));
248     RETURN_IF_ERROR(param.readFromParameter(&config.band));
249     RETURN_IF_ERROR(param.readFromValue(&enable));
250     RETURN_IF_ERROR(param.readFromValue(&config.cutoffFrequencyHz));
251     RETURN_IF_ERROR(param.readFromValue(&config.gainDb));
252 
253     config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
254     return config;
255 }
256 
257 ConversionResult<DynamicsProcessing::MbcBandConfig>
readMbcBandConfigFromParam(EffectParamReader & param)258 AidlConversionDp::readMbcBandConfigFromParam(EffectParamReader& param) {
259     DynamicsProcessing::MbcBandConfig config;
260     int32_t enable;
261     RETURN_IF_ERROR(param.readFromParameter(&config.channel));
262     RETURN_IF_ERROR(param.readFromParameter(&config.band));
263     RETURN_IF_ERROR(param.readFromValue(&enable));
264     RETURN_IF_ERROR(param.readFromValue(&config.cutoffFrequencyHz));
265     RETURN_IF_ERROR(param.readFromValue(&config.attackTimeMs));
266     RETURN_IF_ERROR(param.readFromValue(&config.releaseTimeMs));
267     RETURN_IF_ERROR(param.readFromValue(&config.ratio));
268     RETURN_IF_ERROR(param.readFromValue(&config.thresholdDb));
269     RETURN_IF_ERROR(param.readFromValue(&config.kneeWidthDb));
270     RETURN_IF_ERROR(param.readFromValue(&config.noiseGateThresholdDb));
271     RETURN_IF_ERROR(param.readFromValue(&config.expanderRatio));
272     RETURN_IF_ERROR(param.readFromValue(&config.preGainDb));
273     RETURN_IF_ERROR(param.readFromValue(&config.postGainDb));
274 
275     config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
276     return config;
277 }
278 
279 ConversionResult<DynamicsProcessing::LimiterConfig>
readLimiterConfigFromParam(EffectParamReader & param)280 AidlConversionDp::readLimiterConfigFromParam(EffectParamReader& param) {
281     DynamicsProcessing::LimiterConfig config;
282     int32_t enable, inUse;
283     RETURN_IF_ERROR(param.readFromParameter(&config.channel));
284     RETURN_IF_ERROR(param.readFromValue(&inUse));
285     RETURN_IF_ERROR(param.readFromValue(&enable));
286     RETURN_IF_ERROR(param.readFromValue(&config.linkGroup));
287     RETURN_IF_ERROR(param.readFromValue(&config.attackTimeMs));
288     RETURN_IF_ERROR(param.readFromValue(&config.releaseTimeMs));
289     RETURN_IF_ERROR(param.readFromValue(&config.ratio));
290     RETURN_IF_ERROR(param.readFromValue(&config.thresholdDb));
291     RETURN_IF_ERROR(param.readFromValue(&config.postGainDb));
292 
293     config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
294     return config;
295 }
296 
297 ConversionResult<DynamicsProcessing::EngineArchitecture>
readEngineArchitectureFromParam(EffectParamReader & param)298 AidlConversionDp::readEngineArchitectureFromParam(EffectParamReader& param) {
299     DynamicsProcessing::EngineArchitecture engine;
300     int32_t variant, preEqInUse, mbcInUse, postEqInUse, limiterInUse;
301     RETURN_IF_ERROR(param.readFromValue(&variant));
302     RETURN_IF_ERROR(param.readFromValue(&engine.preferredProcessingDurationMs));
303     RETURN_IF_ERROR(param.readFromValue(&preEqInUse));
304     RETURN_IF_ERROR(param.readFromValue(&engine.preEqStage.bandCount));
305     RETURN_IF_ERROR(param.readFromValue(&mbcInUse));
306     RETURN_IF_ERROR(param.readFromValue(&engine.mbcStage.bandCount));
307     RETURN_IF_ERROR(param.readFromValue(&postEqInUse));
308     RETURN_IF_ERROR(param.readFromValue(&engine.postEqStage.bandCount));
309     RETURN_IF_ERROR(param.readFromValue(&limiterInUse));
310 
311     engine.resolutionPreference = VALUE_OR_RETURN(
312             aidl::android::legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(variant));
313     engine.preEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(preEqInUse));
314     engine.mbcStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(mbcInUse));
315     engine.postEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(postEqInUse));
316     engine.limiterInUse = VALUE_OR_RETURN(convertIntegral<bool>(limiterInUse));
317     return engine;
318 }
319 
getChannelConfig(DynamicsProcessing::Tag tag,EffectParamWriter & param)320 status_t AidlConversionDp::getChannelConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
321     int32_t channel;
322     RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
323 
324     Parameter aidlParam;
325     Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
326     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
327 
328     std::vector<DynamicsProcessing::ChannelConfig> channels;
329     int32_t inUse, bandCount;
330     switch (tag) {
331         case DynamicsProcessing::preEq: {
332             inUse = mEngine.preEqStage.inUse;
333             bandCount = mEngine.preEqStage.bandCount;
334             channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
335                     aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::preEq,
336                     std::vector<DynamicsProcessing::ChannelConfig>));
337             break;
338         }
339         case DynamicsProcessing::postEq: {
340             inUse = mEngine.postEqStage.inUse;
341             bandCount = mEngine.postEqStage.bandCount;
342             channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
343                     aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::postEq,
344                     std::vector<DynamicsProcessing::ChannelConfig>));
345             break;
346         }
347         case DynamicsProcessing::mbc: {
348             inUse = mEngine.mbcStage.inUse;
349             bandCount = mEngine.mbcStage.bandCount;
350             channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
351                     aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::mbc,
352                     std::vector<DynamicsProcessing::ChannelConfig>));
353             break;
354         }
355         default: {
356             ALOGE("%s unsupported tag %s", __func__, toString(tag).c_str());
357             return BAD_VALUE;
358         }
359     }
360 
361     for (const auto& ch : channels) {
362         if (ch.channel == channel) {
363             int32_t enable = ch.enable;
364             RETURN_STATUS_IF_ERROR(param.writeToValue(&inUse));
365             RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
366             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandCount));
367             return OK;
368         }
369     }
370     ALOGE("%s not able to find channel %d", __func__, channel);
371     return BAD_VALUE;
372 }
373 
getEqBandConfig(DynamicsProcessing::Tag tag,EffectParamWriter & param)374 status_t AidlConversionDp::getEqBandConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
375     int32_t channel, band;
376     RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
377     RETURN_STATUS_IF_ERROR(param.readFromParameter(&band));
378 
379     Parameter aidlParam;
380     Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
381     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
382 
383     std::vector<DynamicsProcessing::EqBandConfig> bands;
384     if (tag == DynamicsProcessing::preEqBand) {
385         bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
386                 aidlParam, DynamicsProcessing, dynamicsProcessing, preEqBand,
387                 std::vector<DynamicsProcessing::EqBandConfig>));
388     } else if (tag == DynamicsProcessing::postEqBand) {
389         bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
390                 aidlParam, DynamicsProcessing, dynamicsProcessing, postEqBand,
391                 std::vector<DynamicsProcessing::EqBandConfig>));
392     } else {
393         return BAD_VALUE;
394     }
395 
396     for (const auto& bandIt : bands) {
397         if (bandIt.channel == channel && bandIt.band == band) {
398             int32_t enable = bandIt.enable;
399             RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
400             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.cutoffFrequencyHz));
401             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.gainDb));
402             return OK;
403         }
404     }
405     ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
406     return BAD_VALUE;
407 }
408 
getMbcBandConfig(EffectParamWriter & param)409 status_t AidlConversionDp::getMbcBandConfig(EffectParamWriter& param) {
410     int32_t channel, band;
411     RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
412     RETURN_STATUS_IF_ERROR(param.readFromParameter(&band));
413     Parameter aidlParam;
414     Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
415                                                   DynamicsProcessing::mbcBand);
416     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
417 
418     std::vector<DynamicsProcessing::MbcBandConfig> bands =
419             VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
420                     aidlParam, DynamicsProcessing, dynamicsProcessing, mbcBand,
421                     std::vector<DynamicsProcessing::MbcBandConfig>));
422 
423     for (const auto& bandIt : bands) {
424         if (bandIt.channel == channel && bandIt.band == band) {
425             int32_t enable = bandIt.enable;
426             RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
427             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.cutoffFrequencyHz));
428             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.attackTimeMs));
429             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.releaseTimeMs));
430             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.ratio));
431             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.thresholdDb));
432             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.kneeWidthDb));
433             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.noiseGateThresholdDb));
434             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.expanderRatio));
435             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.preGainDb));
436             RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.postGainDb));
437             return OK;
438         }
439     }
440     ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
441     return BAD_VALUE;
442 }
443 
getLimiterConfig(EffectParamWriter & param)444 status_t AidlConversionDp::getLimiterConfig(EffectParamWriter& param) {
445     int32_t channel;
446     RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
447     Parameter aidlParam;
448     Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
449                                                   DynamicsProcessing::limiter);
450     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
451 
452     std::vector<DynamicsProcessing::LimiterConfig> configs =
453             VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
454                     aidlParam, DynamicsProcessing, dynamicsProcessing, limiter,
455                     std::vector<DynamicsProcessing::LimiterConfig>));
456 
457     for (const auto& config : configs) {
458         if (config.channel == channel) {
459             int32_t inUse = mEngine.limiterInUse;
460             int32_t enable = config.enable;
461             RETURN_STATUS_IF_ERROR(param.writeToValue(&inUse));
462             RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
463             RETURN_STATUS_IF_ERROR(param.writeToValue(&config.linkGroup));
464             RETURN_STATUS_IF_ERROR(param.writeToValue(&config.attackTimeMs));
465             RETURN_STATUS_IF_ERROR(param.writeToValue(&config.releaseTimeMs));
466             RETURN_STATUS_IF_ERROR(param.writeToValue(&config.ratio));
467             RETURN_STATUS_IF_ERROR(param.writeToValue(&config.thresholdDb));
468             RETURN_STATUS_IF_ERROR(param.writeToValue(&config.postGainDb));
469             return OK;
470         }
471     }
472     ALOGE("%s not able to find channel %d", __func__, channel);
473     return BAD_VALUE;
474 }
475 
476 } // namespace effect
477 } // namespace android
478