blob: df1f9bd0caac3830c85e2df7be6d7906a4e18622 [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>
Shunkai Yao242521c2023-01-29 18:08:09 +000019#define LOG_TAG "AidlConversionSpatializer"
20//#define LOG_NDEBUG 0
21
Shunkai Yaoda4a6402023-03-03 19:38:17 +000022#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
23#include <aidl/android/hardware/audio/effect/VendorExtension.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000024#include <error/expected_utils.h>
Shunkai Yaoec116bf2024-02-13 01:57:36 +000025#include <media/AidlConversionCppNdk.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000026#include <media/AidlConversionEffect.h>
Shunkai Yaoec116bf2024-02-13 01:57:36 +000027#include <media/AidlConversionNdk.h>
28#include <system/audio_effects/aidl_effects_utils.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000029#include <system/audio_effects/effect_spatializer.h>
Shunkai Yao242521c2023-01-29 18:08:09 +000030#include <utils/Log.h>
31
32#include "AidlConversionSpatializer.h"
33
34namespace android {
35namespace effect {
36
Shunkai Yaoec116bf2024-02-13 01:57:36 +000037using aidl::android::getParameterSpecificField;
38using aidl::android::aidl_utils::statusTFromBinderStatus;
39using aidl::android::hardware::audio::common::SourceMetadata;
40using aidl::android::hardware::audio::effect::DefaultExtension;
41using aidl::android::hardware::audio::effect::Parameter;
42using aidl::android::hardware::audio::effect::Range;
43using aidl::android::hardware::audio::effect::Spatializer;
44using aidl::android::hardware::audio::effect::VendorExtension;
45using aidl::android::media::audio::common::AudioChannelLayout;
46using aidl::android::media::audio::common::HeadTracking;
47using aidl::android::media::audio::common::Spatialization;
48using aidl::android::media::audio::common::toString;
49using android::status_t;
Shunkai Yao242521c2023-01-29 18:08:09 +000050using utils::EffectParamReader;
51using utils::EffectParamWriter;
52
Shunkai Yaoec116bf2024-02-13 01:57:36 +000053bool AidlConversionSpatializer::isSpatializerParameterSupported() {
54 return mIsSpatializerAidlParamSupported.value_or(
55 (mIsSpatializerAidlParamSupported =
56 [&]() {
57 ::aidl::android::hardware::audio::effect::Parameter aidlParam;
58 auto id = MAKE_SPECIFIC_PARAMETER_ID(Spatializer, spatializerTag,
59 Spatializer::vendor);
60 // No range defined in descriptor capability means no Spatializer AIDL
61 // implementation BAD_VALUE return from getParameter indicates the
62 // parameter is not supported by HAL
63 return mDesc.capability.range.getTag() == Range::spatializer &&
64 mEffect->getParameter(id, &aidlParam).getStatus() !=
65 android::BAD_VALUE;
66 }())
67 .value());
68}
69
Shunkai Yao242521c2023-01-29 18:08:09 +000070status_t AidlConversionSpatializer::setParameter(EffectParamReader& param) {
Shunkai Yaoec116bf2024-02-13 01:57:36 +000071 Parameter aidlParam;
72 if (isSpatializerParameterSupported()) {
73 uint32_t command = 0;
74 if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int8_t)) ||
75 OK != param.readFromParameter(&command)) {
76 ALOGE("%s %d invalid param %s", __func__, __LINE__, param.toString().c_str());
77 return BAD_VALUE;
78 }
79
80 switch (command) {
81 case SPATIALIZER_PARAM_LEVEL: {
82 Spatialization::Level level = Spatialization::Level::NONE;
83 if (OK != param.readFromValue(&level)) {
84 ALOGE("%s invalid level value %s", __func__, param.toString().c_str());
85 return BAD_VALUE;
86 }
87 aidlParam = MAKE_SPECIFIC_PARAMETER(Spatializer, spatializer,
88 spatializationLevel, level);
89 break;
90 }
91 case SPATIALIZER_PARAM_HEADTRACKING_MODE: {
92 HeadTracking::Mode mode = HeadTracking::Mode::DISABLED;
93 if (OK != param.readFromValue(&mode)) {
94 ALOGE("%s invalid mode value %s", __func__, param.toString().c_str());
95 return BAD_VALUE;
96 }
97 aidlParam = MAKE_SPECIFIC_PARAMETER(Spatializer, spatializer, headTrackingMode,
98 mode);
99 break;
100 }
101 case SPATIALIZER_PARAM_HEAD_TO_STAGE: {
102 const size_t valueSize = param.getValueSize();
103 if (valueSize / sizeof(float) > 6 || valueSize % sizeof(float) != 0) {
104 ALOGE("%s invalid parameter value size %zu", __func__, valueSize);
105 return BAD_VALUE;
106 }
107 std::array<float, 6> headToStage = {};
108 for (size_t i = 0; i < valueSize / sizeof(float); i++) {
109 if (OK != param.readFromValue(&headToStage[i])) {
110 ALOGE("%s failed to read headToStage from %s", __func__,
111 param.toString().c_str());
112 return BAD_VALUE;
113 }
114 }
115 HeadTracking::SensorData sensorData =
116 HeadTracking::SensorData::make<HeadTracking::SensorData::headToStage>(
117 headToStage);
118 aidlParam = MAKE_SPECIFIC_PARAMETER(Spatializer, spatializer,
119 headTrackingSensorData, sensorData);
120 break;
121 }
122 case SPATIALIZER_PARAM_HEADTRACKING_CONNECTION: {
123 int32_t modeInt32 = 0;
124 int32_t sensorId = -1;
125 if (OK != param.readFromValue(&modeInt32) || OK != param.readFromValue(&sensorId)) {
126 ALOGE("%s %d invalid parameter value %s", __func__, __LINE__,
127 param.toString().c_str());
128 return BAD_VALUE;
129 }
130
131 const auto mode = static_cast<HeadTracking::ConnectionMode>(modeInt32);
132 if (mode < *ndk::enum_range<HeadTracking::ConnectionMode>().begin() ||
133 mode > *ndk::enum_range<HeadTracking::ConnectionMode>().end()) {
134 ALOGE("%s %d invalid mode %d", __func__, __LINE__, modeInt32);
135 return BAD_VALUE;
136 }
137 aidlParam = MAKE_SPECIFIC_PARAMETER(Spatializer, spatializer,
138 headTrackingConnectionMode, mode);
139 if (status_t status = statusTFromBinderStatus(mEffect->setParameter(aidlParam));
140 status != OK) {
141 ALOGE("%s failed to set headTrackingConnectionMode %s", __func__,
142 toString(mode).c_str());
143 return status;
144 }
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000145 aidlParam = MAKE_SPECIFIC_PARAMETER(Spatializer, spatializer, headTrackingSensorId,
146 sensorId);
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000147 return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
148 }
149 default: {
150 ALOGE("%s %d invalid command %u", __func__, __LINE__, command);
151 return BAD_VALUE;
152 }
153 }
154 } else {
155 aidlParam = VALUE_OR_RETURN_STATUS(
156 ::aidl::android::legacy2aidl_EffectParameterReader_Parameter(param));
157 }
158
Shunkai Yao242521c2023-01-29 18:08:09 +0000159 return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
160}
161
162status_t AidlConversionSpatializer::getParameter(EffectParamWriter& param) {
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000163 if (isSpatializerParameterSupported()) {
164 uint32_t command = 0;
165 if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int8_t)) ||
166 OK != param.readFromParameter(&command)) {
167 ALOGE("%s %d invalid param %s", __func__, __LINE__, param.toString().c_str());
168 return BAD_VALUE;
169 }
Shunkai Yaoda4a6402023-03-03 19:38:17 +0000170
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000171 switch (command) {
172 case SPATIALIZER_PARAM_SUPPORTED_LEVELS: {
173 const auto& range = getRange<Range::spatializer, Range::SpatializerRange>(
174 mDesc.capability, Spatializer::spatializationLevel);
175 if (!range) {
176 return BAD_VALUE;
177 }
Shunkai Yaob8821d52024-03-28 21:05:35 +0000178 std::vector<Spatialization::Level> levels;
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000179 for (const auto level : ::ndk::enum_range<Spatialization::Level>()) {
180 const auto spatializer =
181 Spatializer::make<Spatializer::spatializationLevel>(level);
182 if (spatializer >= range->min && spatializer <= range->max) {
Shunkai Yaob8821d52024-03-28 21:05:35 +0000183 levels.emplace_back(level);
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000184 }
185 }
Shunkai Yaob8821d52024-03-28 21:05:35 +0000186 const uint8_t num = levels.size();
187 RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
188 for (const auto level : levels) {
189 RETURN_STATUS_IF_ERROR(param.writeToValue(&level));
190 }
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000191 return OK;
192 }
193 case SPATIALIZER_PARAM_LEVEL: {
194 Parameter aidlParam;
195 Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Spatializer, spatializerTag,
196 Spatializer::spatializationLevel);
197 RETURN_STATUS_IF_ERROR(
198 statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
199 const auto level = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
200 aidlParam, Spatializer, spatializer, Spatializer::spatializationLevel,
201 Spatialization::Level));
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000202 return param.writeToValue(&level);
203 }
204 case SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED: {
205 const auto& range = getRange<Range::spatializer, Range::SpatializerRange>(
206 mDesc.capability, Spatializer::spatializationLevel);
207 if (!range) {
208 ALOGE("%s %d: range not defined for spatializationLevel", __func__, __LINE__);
209 return BAD_VALUE;
210 }
211 const auto& nonSupport = Spatializer::make<Spatializer::spatializationLevel>(
212 Spatialization::Level::NONE);
213 const bool support = (range->min > range->max ||
214 (range->min == nonSupport && range->max == nonSupport))
215 ? false
216 : true;
217 return param.writeToValue(&support);
218 }
219 case SPATIALIZER_PARAM_HEADTRACKING_MODE: {
220 Parameter aidlParam;
221 Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Spatializer, spatializerTag,
222 Spatializer::headTrackingMode);
223 RETURN_STATUS_IF_ERROR(
224 statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
225 const auto mode = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
226 aidlParam, Spatializer, spatializer, Spatializer::headTrackingMode,
227 HeadTracking::Mode));
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000228 return param.writeToValue(&mode);
229 }
230 case SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS: {
231 Parameter aidlParam;
232 Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Spatializer, spatializerTag,
233 Spatializer::supportedChannelLayout);
234 RETURN_STATUS_IF_ERROR(
235 statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
236 const auto& supportedLayouts = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
237 aidlParam, Spatializer, spatializer, Spatializer::supportedChannelLayout,
238 std::vector<AudioChannelLayout>));
Shunkai Yaob8821d52024-03-28 21:05:35 +0000239 // audio_channel_mask_t is uint32_t enum, write number in 32bit
240 const uint32_t num = supportedLayouts.size();
241 RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000242 for (const auto& layout : supportedLayouts) {
243 audio_channel_mask_t mask = VALUE_OR_RETURN_STATUS(
244 ::aidl::android::aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
245 layout, false /* isInput */));
Shunkai Yaob8821d52024-03-28 21:05:35 +0000246 RETURN_STATUS_IF_ERROR(param.writeToValue(&mask));
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000247 }
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000248 return OK;
249 }
250 case SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES: {
251 const auto& range = getRange<Range::spatializer, Range::SpatializerRange>(
252 mDesc.capability, Spatializer::spatializationMode);
253 if (!range) {
254 return BAD_VALUE;
255 }
Shunkai Yaob8821d52024-03-28 21:05:35 +0000256 std::vector<Spatialization::Mode> modes;
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000257 for (const auto mode : ::ndk::enum_range<Spatialization::Mode>()) {
258 if (const auto spatializer =
259 Spatializer::make<Spatializer::spatializationMode>(mode);
260 spatializer >= range->min && spatializer <= range->max) {
Shunkai Yaob8821d52024-03-28 21:05:35 +0000261 modes.emplace_back(mode);
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000262 }
263 }
Shunkai Yaob8821d52024-03-28 21:05:35 +0000264 const uint8_t num = modes.size();
265 RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
266 for (const auto mode : modes) {
267 RETURN_STATUS_IF_ERROR(param.writeToValue(&mode));
268 }
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000269 return OK;
270 }
271 case SPATIALIZER_PARAM_SUPPORTED_HEADTRACKING_CONNECTION: {
272 const auto& range = getRange<Range::spatializer, Range::SpatializerRange>(
273 mDesc.capability, Spatializer::headTrackingConnectionMode);
274 if (!range) {
275 return BAD_VALUE;
276 }
Shunkai Yaob8821d52024-03-28 21:05:35 +0000277 std::vector<HeadTracking::ConnectionMode> modes;
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000278 for (const auto mode : ::ndk::enum_range<HeadTracking::ConnectionMode>()) {
279 if (const auto spatializer =
280 Spatializer::make<Spatializer::headTrackingConnectionMode>(mode);
281 spatializer < range->min || spatializer > range->max) {
Shunkai Yaob8821d52024-03-28 21:05:35 +0000282 modes.emplace_back(mode);
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000283 }
Shunkai Yaob8821d52024-03-28 21:05:35 +0000284 }
285 const uint8_t num = modes.size();
286 RETURN_STATUS_IF_ERROR(param.writeToValue(&num));
287 for (const auto mode : modes) {
288 RETURN_STATUS_IF_ERROR(param.writeToValue(&mode));
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000289 }
290 return OK;
291 }
292 case SPATIALIZER_PARAM_HEADTRACKING_CONNECTION: {
293 status_t status = OK;
294 Parameter aidlParam;
295 Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(
296 Spatializer, spatializerTag, Spatializer::headTrackingConnectionMode);
297 RETURN_STATUS_IF_ERROR(
298 statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
299 const auto mode = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
300 aidlParam, Spatializer, spatializer,
301 Spatializer::headTrackingConnectionMode, HeadTracking::ConnectionMode));
302
303 id = MAKE_SPECIFIC_PARAMETER_ID(Spatializer, spatializerTag,
304 Spatializer::headTrackingSensorId);
305 RETURN_STATUS_IF_ERROR(
306 statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
307 const auto sensorId = VALUE_OR_RETURN_STATUS(
308 GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Spatializer, spatializer,
309 Spatializer::headTrackingSensorId, int32_t));
310 uint32_t modeInt32 = static_cast<int32_t>(mode);
311 if (status = param.writeToValue(&modeInt32); status != OK) {
Shunkai Yaoac61ee92024-03-14 21:57:46 +0000312 ALOGW("%s %d: write mode %s to value failed %d", __func__, __LINE__,
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000313 toString(mode).c_str(), status);
314 return status;
315 }
316 if (status = param.writeToValue(&sensorId); status != OK) {
Shunkai Yaoac61ee92024-03-14 21:57:46 +0000317 ALOGW("%s %d: write sensorId %d to value failed %d", __func__, __LINE__,
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000318 sensorId, status);
319 return status;
320 }
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000321 return OK;
322 }
323 default: {
324 ALOGE("%s %d invalid command %u", __func__, __LINE__, command);
325 return BAD_VALUE;
326 }
327 }
328 } else {
329 Parameter aidlParam;
330 DefaultExtension defaultExt;
331 // read parameters into DefaultExtension vector<uint8_t>
332 defaultExt.bytes.resize(param.getParameterSize());
333 if (OK != param.readFromParameter(defaultExt.bytes.data(), param.getParameterSize())) {
334 ALOGE("%s %d invalid param %s", __func__, __LINE__, param.toString().c_str());
335 param.setStatus(BAD_VALUE);
336 return BAD_VALUE;
337 }
338
339 VendorExtension idTag;
340 idTag.extension.setParcelable(defaultExt);
341 Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, idTag);
342 RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
Shunkai Yaoec116bf2024-02-13 01:57:36 +0000343 // copy the AIDL extension data back to effect_param_t
344 return VALUE_OR_RETURN_STATUS(
345 ::aidl::android::aidl2legacy_Parameter_EffectParameterWriter(aidlParam, param));
346 }
Shunkai Yao242521c2023-01-29 18:08:09 +0000347}
348
349} // namespace effect
350} // namespace android