blob: 787920054a999a5281a89b898d4780306e553cf4 [file] [log] [blame]
Shunkai Yao242521c2023-01-29 18:08:09 +00001/*
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>
Shunkai Yaof9446572024-06-12 17:56:32 +000020#include <unordered_set>
Shunkai Yao242521c2023-01-29 18:08:09 +000021#define LOG_TAG "AidlConversionEQ"
22//#define LOG_NDEBUG 0
23
24#include <error/expected_utils.h>
25#include <media/AidlConversionNdk.h>
26#include <media/AidlConversionEffect.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000027#include <system/audio_effects/effect_equalizer.h>
28
29#include <utils/Log.h>
30
31#include "AidlConversionEq.h"
32
33namespace android {
34namespace effect {
35
36using ::aidl::android::getParameterSpecificField;
37using ::aidl::android::aidl_utils::statusTFromBinderStatus;
38using ::aidl::android::hardware::audio::effect::Equalizer;
39using ::aidl::android::hardware::audio::effect::Parameter;
Shunkai Yao5a6f5442023-02-21 17:58:46 +000040using ::aidl::android::hardware::audio::effect::Range;
Shunkai Yaoda4a6402023-03-03 19:38:17 +000041using ::aidl::android::hardware::audio::effect::VendorExtension;
Shunkai Yao5a6f5442023-02-21 17:58:46 +000042using ::android::base::unexpected;
Shunkai Yao242521c2023-01-29 18:08:09 +000043using ::android::status_t;
44using utils::EffectParamReader;
45using utils::EffectParamWriter;
46
47status_t AidlConversionEq::setParameter(EffectParamReader& param) {
48 uint32_t type;
Shunkai Yao5a6f5442023-02-21 17:58:46 +000049 if (OK != param.readFromParameter(&type)) {
Shunkai Yao242521c2023-01-29 18:08:09 +000050 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
51 return BAD_VALUE;
52 }
53
54 Parameter aidlParam;
55 switch (type) {
56 case EQ_PARAM_CUR_PRESET: {
Shunkai Yao5a6f5442023-02-21 17:58:46 +000057 uint16_t value = 0;
58 if (OK != param.readFromValue(&value)) {
59 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
60 return BAD_VALUE;
61 }
Shunkai Yao242521c2023-01-29 18:08:09 +000062 aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
Shunkai Yaoda4a6402023-03-03 19:38:17 +000063 break;
Shunkai Yao242521c2023-01-29 18:08:09 +000064 }
65 case EQ_PARAM_BAND_LEVEL: {
66 int32_t band;
Shunkai Yao5a6f5442023-02-21 17:58:46 +000067 int16_t level;
68 if (OK != param.readFromParameter(&band) || OK != param.readFromValue(&level)) {
Shunkai Yao242521c2023-01-29 18:08:09 +000069 ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
70 return BAD_VALUE;
71 }
72 std::vector<Equalizer::BandLevel> bandLevels = {{.index = band, .levelMb = level}};
73 aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
Shunkai Yaoda4a6402023-03-03 19:38:17 +000074 break;
Shunkai Yao242521c2023-01-29 18:08:09 +000075 }
76 case EQ_PARAM_PROPERTIES: {
Shunkai Yao5a6f5442023-02-21 17:58:46 +000077 int16_t num;
78 if (OK != param.readFromValue(&num)) {
79 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
80 return BAD_VALUE;
81 }
82 // set preset if it's valid
83 if (num >= 0) {
84 aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)num);
Shunkai Yaoda4a6402023-03-03 19:38:17 +000085 break;
Shunkai Yao5a6f5442023-02-21 17:58:46 +000086 }
87 // set bandLevel if no preset was set
88 if (OK != param.readFromValue(&num)) {
89 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
90 return BAD_VALUE;
91 }
92 std::vector<Equalizer::BandLevel> bandLevels;
93 for (int i = 0; i < num; i++) {
94 Equalizer::BandLevel level({.index = i});
95 if (OK != param.readFromValue((uint16_t*)&level.levelMb)) {
96 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
97 return BAD_VALUE;
98 }
99 bandLevels.push_back(level);
100 }
101 aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
Shunkai Yaoda4a6402023-03-03 19:38:17 +0000102 break;
Shunkai Yao242521c2023-01-29 18:08:09 +0000103 }
104 default: {
Shunkai Yaoda4a6402023-03-03 19:38:17 +0000105 // for vendor extension, copy data area to the DefaultExtension, parameter ignored
106 VendorExtension ext = VALUE_OR_RETURN_STATUS(
Shunkai Yaodbd06942023-06-29 18:07:09 +0000107 aidl::android::legacy2aidl_EffectParameterReader_VendorExtension(param));
Shunkai Yaoda4a6402023-03-03 19:38:17 +0000108 aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, vendor, ext);
109 break;
Shunkai Yao242521c2023-01-29 18:08:09 +0000110 }
111 }
Shunkai Yaoda4a6402023-03-03 19:38:17 +0000112
113 return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
Shunkai Yao242521c2023-01-29 18:08:09 +0000114}
115
Mikhail Naganov19418e32023-03-10 17:55:14 -0800116ConversionResult<Parameter> AidlConversionEq::getAidlParameter(Equalizer::Tag tag) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000117 Parameter aidlParam;
118 Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Equalizer, equalizerTag, tag);
119 RETURN_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
120 return aidlParam;
121}
122
Mikhail Naganov19418e32023-03-10 17:55:14 -0800123ConversionResult<int32_t> AidlConversionEq::getParameterPreset() {
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000124 Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::preset));
125 return VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Equalizer, equalizer,
126 Equalizer::preset, int32_t));
127}
128
Mikhail Naganov19418e32023-03-10 17:55:14 -0800129ConversionResult<std::string> AidlConversionEq::getParameterPresetName(
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000130 EffectParamWriter& param) {
131 int32_t presetIdx;
132 if (OK != param.readFromParameter(&presetIdx)) {
133 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
134 return unexpected(BAD_VALUE);
135 }
136 Parameter aidlParam = VALUE_OR_RETURN(getAidlParameter(Equalizer::presets));
137 const auto& presets = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
138 aidlParam, Equalizer, equalizer, Equalizer::presets, std::vector<Equalizer::Preset>));
139 for (const auto& preset : presets) {
140 if (presetIdx == preset.index) {
141 return preset.name;
142 }
143 }
144 return unexpected(BAD_VALUE);
145}
146
Shunkai Yao242521c2023-01-29 18:08:09 +0000147status_t AidlConversionEq::getParameter(EffectParamWriter& param) {
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000148 uint32_t type = 0;
149 if (OK != param.readFromParameter(&type)) {
Shunkai Yao242521c2023-01-29 18:08:09 +0000150 param.setStatus(BAD_VALUE);
151 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
152 return BAD_VALUE;
153 }
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000154
Shunkai Yao242521c2023-01-29 18:08:09 +0000155 switch (type) {
156 case EQ_PARAM_NUM_BANDS: {
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000157 Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
158 const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
Shunkai Yao242521c2023-01-29 18:08:09 +0000159 aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
160 std::vector<Equalizer::BandLevel>));
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000161 uint16_t bands = bandLevels.size();
162 return param.writeToValue(&bands);
163 }
164 case EQ_PARAM_LEVEL_RANGE: {
Shunkai Yaob0303dd2023-05-24 01:40:02 +0000165 if (mDesc.capability.range.getTag() != Range::equalizer) {
166 return OK;
167 }
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000168 const auto& ranges = mDesc.capability.range.get<Range::equalizer>();
169 for (const auto& r : ranges) {
170 if (r.min.getTag() == Equalizer::bandLevels &&
171 r.max.getTag() == Equalizer::bandLevels) {
172 const auto& aidlMin = r.min.get<Equalizer::bandLevels>();
173 const auto& aidlMax = r.max.get<Equalizer::bandLevels>();
174 int16_t min =
175 std::min_element(aidlMin.begin(), aidlMin.end(), [](auto& a, auto& b) {
176 return a.levelMb < b.levelMb;
177 })->levelMb;
178 int16_t max =
179 std::max_element(aidlMax.begin(), aidlMax.end(), [](auto& a, auto& b) {
180 return a.levelMb < b.levelMb;
181 })->levelMb;
182 return (OK == param.writeToValue(&min) && OK == param.writeToValue(&max))
183 ? OK
184 : BAD_VALUE;
185 }
186 }
187 break;
188 }
189 case EQ_PARAM_BAND_LEVEL: {
190 int32_t bandIdx;
191 if (OK != param.readFromParameter(&bandIdx)) {
192 break;
193 }
194
195 Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
196 const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
197 aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
198 std::vector<Equalizer::BandLevel>));
199 for (const auto& band : bandLevels) {
200 if (band.index == bandIdx) {
201 return param.writeToValue((uint16_t *)&band.levelMb);
202 }
203 }
204 break;
205 }
206 case EQ_PARAM_CENTER_FREQ: {
207 int32_t index;
208 if (OK != param.readFromParameter(&index)) {
209 break;
210 }
211
212 Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::centerFreqMh));
213 const auto& freqs = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
214 aidlParam, Equalizer, equalizer, Equalizer::centerFreqMh, std::vector<int>));
215 if ((size_t)index >= freqs.size()) {
216 ALOGE("%s index %d exceed size %zu", __func__, index, freqs.size());
217 break;
218 }
219 return param.writeToValue(&freqs[index]);
220 }
221 case EQ_PARAM_BAND_FREQ_RANGE: {
222 int32_t index;
223 if (OK != param.readFromParameter(&index)) {
224 break;
225 }
226
227 Parameter aidlParam =
228 VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
229 const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
230 aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
231 std::vector<Equalizer::BandFrequency>));
232 for (const auto& band : bands) {
233 if (band.index == index) {
234 return (OK == param.writeToValue(&band.minMh) &&
235 OK == param.writeToValue(&band.maxMh))
236 ? OK
237 : BAD_VALUE;
238 }
239 }
240 break;
241 }
242 case EQ_PARAM_GET_BAND: {
243 int32_t freq;
244 if (OK != param.readFromParameter(&freq)) {
245 break;
246 }
247
248 Parameter aidlParam =
249 VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
250 const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
251 aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
252 std::vector<Equalizer::BandFrequency>));
253 for (const auto& band : bands) {
254 if (freq >= band.minMh && freq <= band.maxMh) {
255 return param.writeToValue((uint16_t*)&band.index);
256 }
257 }
258 break;
259 }
260 case EQ_PARAM_CUR_PRESET: {
261 int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
262 return param.writeToValue((uint16_t*)&preset);
263 }
264 case EQ_PARAM_GET_NUM_OF_PRESETS: {
265 Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::presets));
Shunkai Yaof9446572024-06-12 17:56:32 +0000266 auto presets = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000267 aidlParam, Equalizer, equalizer, Equalizer::presets,
268 std::vector<Equalizer::Preset>));
Shunkai Yaof9446572024-06-12 17:56:32 +0000269 // it was assumed the presets index in the range of [0, NUM_OF_PRESETS - 1], so
270 // filter out presets out of this range (one example is preset {-1, "custom"})
271 std::erase_if(presets, [](const auto& preset) { return preset.index < 0; });
272 // validate remaining indexes are unique [0, num - 1]
273 std::unordered_set<uint16_t> uniqueIndices;
274 const uint16_t num = presets.size();
275 for (const auto& preset : presets) {
276 if (preset.index >= num || 0 != uniqueIndices.count(preset.index)) {
277 return BAD_VALUE;
278 }
279 uniqueIndices.insert(preset.index);
280 }
Shunkai Yao242521c2023-01-29 18:08:09 +0000281 return param.writeToValue(&num);
282 }
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000283 case EQ_PARAM_GET_PRESET_NAME: {
284 std::string name = VALUE_OR_RETURN_STATUS(getParameterPresetName(param));
285 return param.writeToValue(name.c_str(), name.length());
286 }
287 case EQ_PARAM_PROPERTIES: {
288 int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
289 if (OK != param.writeToValue((uint16_t*)&preset)) {
290 break;
291 }
292 Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
293 std::vector<Equalizer::BandLevel> bandLevels =
294 VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
295 aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
296 std::vector<Equalizer::BandLevel>));
297 uint16_t bands = bandLevels.size();
298 if (OK != param.writeToValue(&bands)) {
299 break;
300 }
301 std::sort(bandLevels.begin(), bandLevels.end(),
302 [](const auto& a, const auto& b) { return a.index < b.index; });
303 for (const auto& level : bandLevels) {
304 if (status_t status = param.writeToValue((uint16_t*)&level.levelMb); status != OK) {
305 return status;
306 }
307 }
308 return OK;
309 }
310 default: {
Shunkai Yaoda4a6402023-03-03 19:38:17 +0000311 VENDOR_EXTENSION_GET_AND_RETURN(Equalizer, equalizer, param);
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000312 }
Shunkai Yao242521c2023-01-29 18:08:09 +0000313 }
Shunkai Yao5a6f5442023-02-21 17:58:46 +0000314
315 param.setStatus(BAD_VALUE);
316 ALOGE("%s invalid param %s", __func__, param.toString().c_str());
317 return BAD_VALUE;
Shunkai Yao242521c2023-01-29 18:08:09 +0000318}
319
320} // namespace effect
321} // namespace android