1 /*
2 * Copyright (C) 2024 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 <inttypes.h>
18
19 #include <unordered_set>
20
21 #define LOG_TAG "AHAL_Config"
22 #include <android-base/logging.h>
23 #include <android-base/strings.h>
24 #include <android/binder_enums.h>
25
26 #include <aidl/android/media/audio/common/AudioPort.h>
27 #include <aidl/android/media/audio/common/AudioPortConfig.h>
28 #include <media/AidlConversionCppNdk.h>
29 #include <media/TypeConverter.h>
30 #include <media/convert.h>
31 #include <utils/FastStrcmp.h>
32
33 #include <Utils.h>
34
35 #include "core-impl/XmlConverter.h"
36 #include "core-impl/XsdcConversion.h"
37
38 using aidl::android::hardware::audio::common::iequals;
39 using aidl::android::hardware::audio::common::isValidAudioMode;
40 using aidl::android::hardware::audio::common::kValidAudioModes;
41 using aidl::android::media::audio::common::AudioChannelLayout;
42 using aidl::android::media::audio::common::AudioContentType;
43 using aidl::android::media::audio::common::AudioDevice;
44 using aidl::android::media::audio::common::AudioDeviceAddress;
45 using aidl::android::media::audio::common::AudioDeviceDescription;
46 using aidl::android::media::audio::common::AudioDeviceType;
47 using aidl::android::media::audio::common::AudioFormatDescription;
48 using aidl::android::media::audio::common::AudioFormatType;
49 using aidl::android::media::audio::common::AudioGain;
50 using aidl::android::media::audio::common::AudioHalCapCriterion;
51 using aidl::android::media::audio::common::AudioHalCapCriterionType;
52 using aidl::android::media::audio::common::AudioHalCapCriterionV2;
53 using aidl::android::media::audio::common::AudioHalVolumeCurve;
54 using aidl::android::media::audio::common::AudioIoFlags;
55 using aidl::android::media::audio::common::AudioMode;
56 using aidl::android::media::audio::common::AudioPolicyForceUse;
57 using aidl::android::media::audio::common::AudioPort;
58 using aidl::android::media::audio::common::AudioPortConfig;
59 using aidl::android::media::audio::common::AudioPortDeviceExt;
60 using aidl::android::media::audio::common::AudioPortExt;
61 using aidl::android::media::audio::common::AudioPortMixExt;
62 using aidl::android::media::audio::common::AudioProfile;
63 using aidl::android::media::audio::common::AudioSource;
64 using aidl::android::media::audio::common::AudioStreamType;
65 using aidl::android::media::audio::common::AudioUsage;
66 using android::BAD_VALUE;
67 using android::base::unexpected;
68 using android::utilities::convertTo;
69 using ndk::enum_range;
70
71 namespace ap_xsd = android::audio::policy::configuration;
72 namespace eng_xsd = android::audio::policy::engine::configuration;
73
74 namespace aidl::android::hardware::audio::core::internal {
75
76 static constexpr const char kXsdcForceConfigForCommunication[] = "ForceUseForCommunication";
77 static constexpr const char kXsdcForceConfigForMedia[] = "ForceUseForMedia";
78 static constexpr const char kXsdcForceConfigForRecord[] = "ForceUseForRecord";
79 static constexpr const char kXsdcForceConfigForDock[] = "ForceUseForDock";
80 static constexpr const char kXsdcForceConfigForSystem[] = "ForceUseForSystem";
81 static constexpr const char kXsdcForceConfigForHdmiSystemAudio[] = "ForceUseForHdmiSystemAudio";
82 static constexpr const char kXsdcForceConfigForEncodedSurround[] = "ForceUseForEncodedSurround";
83 static constexpr const char kXsdcForceConfigForVibrateRinging[] = "ForceUseForVibrateRinging";
84
assertNonEmpty(const std::string & s)85 inline ConversionResult<std::string> assertNonEmpty(const std::string& s) {
86 if (s.empty()) {
87 LOG(ERROR) << __func__ << " Review Audio Policy config: "
88 << " empty string is not valid.";
89 return unexpected(BAD_VALUE);
90 }
91 return s;
92 }
93
94 #define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s))
95
convertAudioFlagsToAidl(const std::vector<eng_xsd::FlagType> & xsdcFlagTypeVec)96 ConversionResult<int32_t> convertAudioFlagsToAidl(
97 const std::vector<eng_xsd::FlagType>& xsdcFlagTypeVec) {
98 int legacyFlagMask = 0;
99 for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
100 if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
101 audio_flags_mask_t legacyFlag = AUDIO_FLAG_NONE;
102 if (!::android::AudioFlagConverter::fromString(eng_xsd::toString(xsdcFlagType),
103 legacyFlag)) {
104 LOG(ERROR) << __func__ << " Review Audio Policy config, "
105 << eng_xsd::toString(xsdcFlagType) << " is not a valid flag.";
106 return unexpected(BAD_VALUE);
107 }
108 legacyFlagMask |= static_cast<int>(legacyFlag);
109 }
110 }
111 ConversionResult<int32_t> result = legacy2aidl_audio_flags_mask_t_int32_t_mask(
112 static_cast<audio_flags_mask_t>(legacyFlagMask));
113 if (!result.ok()) {
114 LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyFlagMask
115 << " has invalid flag(s).";
116 return unexpected(BAD_VALUE);
117 }
118 return result;
119 }
120
convertAudioStreamTypeToAidl(const eng_xsd::Stream & xsdcStream)121 ConversionResult<AudioStreamType> convertAudioStreamTypeToAidl(const eng_xsd::Stream& xsdcStream) {
122 audio_stream_type_t legacyStreamType;
123 if (!::android::StreamTypeConverter::fromString(eng_xsd::toString(xsdcStream),
124 legacyStreamType)) {
125 LOG(ERROR) << __func__ << " Review Audio Policy config, " << eng_xsd::toString(xsdcStream)
126 << " is not a valid audio stream type.";
127 return unexpected(BAD_VALUE);
128 }
129 ConversionResult<AudioStreamType> result =
130 legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStreamType);
131 if (!result.ok()) {
132 LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyStreamType
133 << " is not a valid audio stream type.";
134 return unexpected(BAD_VALUE);
135 }
136 return result;
137 }
138
convertAudioSourceToAidl(const eng_xsd::SourceEnumType & xsdcSourceType)139 ConversionResult<AudioSource> convertAudioSourceToAidl(
140 const eng_xsd::SourceEnumType& xsdcSourceType) {
141 audio_source_t legacySourceType;
142 if (!::android::SourceTypeConverter::fromString(eng_xsd::toString(xsdcSourceType),
143 legacySourceType)) {
144 LOG(ERROR) << __func__ << " Review Audio Policy config, "
145 << eng_xsd::toString(xsdcSourceType) << " is not a valid audio source.";
146 return unexpected(BAD_VALUE);
147 }
148 ConversionResult<AudioSource> result = legacy2aidl_audio_source_t_AudioSource(legacySourceType);
149 if (!result.ok()) {
150 LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacySourceType
151 << " is not a valid audio source.";
152 return unexpected(BAD_VALUE);
153 }
154 return result;
155 }
156
convertAudioContentTypeToAidl(const eng_xsd::ContentType & xsdcContentType)157 ConversionResult<AudioContentType> convertAudioContentTypeToAidl(
158 const eng_xsd::ContentType& xsdcContentType) {
159 audio_content_type_t legacyContentType;
160 if (!::android::AudioContentTypeConverter::fromString(eng_xsd::toString(xsdcContentType),
161 legacyContentType)) {
162 LOG(ERROR) << __func__ << " Review Audio Policy config, "
163 << eng_xsd::toString(xsdcContentType) << " is not a valid audio content type.";
164 return unexpected(BAD_VALUE);
165 }
166 ConversionResult<AudioContentType> result =
167 legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType);
168 if (!result.ok()) {
169 LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyContentType
170 << " is not a valid audio content type.";
171 return unexpected(BAD_VALUE);
172 }
173 return result;
174 }
175
convertAudioUsageToAidl(const eng_xsd::UsageEnumType & xsdcUsage)176 ConversionResult<AudioUsage> convertAudioUsageToAidl(const eng_xsd::UsageEnumType& xsdcUsage) {
177 audio_usage_t legacyUsage;
178 if (!::android::UsageTypeConverter::fromString(eng_xsd::toString(xsdcUsage), legacyUsage)) {
179 LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
180 return unexpected(BAD_VALUE);
181 }
182 ConversionResult<AudioUsage> result = legacy2aidl_audio_usage_t_AudioUsage(legacyUsage);
183 if (!result.ok()) {
184 LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage.";
185 return unexpected(BAD_VALUE);
186 }
187 return result;
188 }
189
convertAudioFormatToAidl(const std::string & xsdcFormat)190 ConversionResult<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) {
191 audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT);
192 ConversionResult<AudioFormatDescription> result =
193 legacy2aidl_audio_format_t_AudioFormatDescription(legacyFormat);
194 if ((legacyFormat == AUDIO_FORMAT_DEFAULT && xsdcFormat.compare("AUDIO_FORMAT_DEFAULT") != 0) ||
195 !result.ok()) {
196 LOG(ERROR) << __func__ << " Review Audio Policy config: " << xsdcFormat
197 << " is not a valid audio format.";
198 return unexpected(BAD_VALUE);
199 }
200 return result;
201 }
202
getAttachedDevices(const ap_xsd::Modules::Module & moduleConfig)203 std::unordered_set<std::string> getAttachedDevices(const ap_xsd::Modules::Module& moduleConfig) {
204 std::unordered_set<std::string> attachedDeviceSet;
205 if (moduleConfig.hasAttachedDevices()) {
206 for (const ap_xsd::AttachedDevices& attachedDevices : moduleConfig.getAttachedDevices()) {
207 if (attachedDevices.hasItem()) {
208 attachedDeviceSet.insert(attachedDevices.getItem().begin(),
209 attachedDevices.getItem().end());
210 }
211 }
212 }
213 return attachedDeviceSet;
214 }
215
convertDeviceTypeToAidl(const std::string & xType)216 ConversionResult<AudioDeviceDescription> convertDeviceTypeToAidl(const std::string& xType) {
217 audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE;
218 ::android::DeviceConverter::fromString(xType, legacyDeviceType);
219 ConversionResult<AudioDeviceDescription> result =
220 legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyDeviceType);
221 if ((legacyDeviceType == AUDIO_DEVICE_NONE) || !result.ok()) {
222 LOG(ERROR) << __func__ << " Review Audio Policy config: " << xType
223 << " is not a valid device type.";
224 return unexpected(BAD_VALUE);
225 }
226 return result;
227 }
228
createAudioDevice(const ap_xsd::DevicePorts::DevicePort & xDevicePort)229 ConversionResult<AudioDevice> createAudioDevice(
230 const ap_xsd::DevicePorts::DevicePort& xDevicePort) {
231 AudioDevice device = {
232 .type = VALUE_OR_FATAL(convertDeviceTypeToAidl(xDevicePort.getType())),
233 .address = xDevicePort.hasAddress()
234 ? AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(
235 xDevicePort.getAddress())
236 : AudioDeviceAddress{}};
237 if (device.type.type == AudioDeviceType::IN_MICROPHONE && device.type.connection.empty()) {
238 device.address = "bottom";
239 } else if (device.type.type == AudioDeviceType::IN_MICROPHONE_BACK &&
240 device.type.connection.empty()) {
241 device.address = "back";
242 }
243 return device;
244 }
245
createAudioPortExt(const ap_xsd::DevicePorts::DevicePort & xDevicePort,const std::string & xDefaultOutputDevice)246 ConversionResult<AudioPortExt> createAudioPortExt(
247 const ap_xsd::DevicePorts::DevicePort& xDevicePort,
248 const std::string& xDefaultOutputDevice) {
249 AudioPortDeviceExt deviceExt = {
250 .device = VALUE_OR_FATAL(createAudioDevice(xDevicePort)),
251 .flags = (xDevicePort.getTagName() == xDefaultOutputDevice)
252 ? 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE
253 : 0,
254 .encodedFormats =
255 xDevicePort.hasEncodedFormats()
256 ? VALUE_OR_FATAL(
257 (convertCollectionToAidl<std::string, AudioFormatDescription>(
258 xDevicePort.getEncodedFormats(),
259 &convertAudioFormatToAidl)))
260 : std::vector<AudioFormatDescription>{},
261 };
262 return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt);
263 }
264
createAudioPortExt(const ap_xsd::MixPorts::MixPort & xMixPort)265 ConversionResult<AudioPortExt> createAudioPortExt(const ap_xsd::MixPorts::MixPort& xMixPort) {
266 AudioPortMixExt mixExt = {
267 .maxOpenStreamCount =
268 xMixPort.hasMaxOpenCount() ? static_cast<int>(xMixPort.getMaxOpenCount()) : 0,
269 .maxActiveStreamCount = xMixPort.hasMaxActiveCount()
270 ? static_cast<int>(xMixPort.getMaxActiveCount())
271 : 1,
272 .recommendedMuteDurationMs =
273 xMixPort.hasRecommendedMuteDurationMs()
274 ? static_cast<int>(xMixPort.getRecommendedMuteDurationMs())
275 : 0};
276 return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt);
277 }
278
convertGainModeToAidl(const std::vector<ap_xsd::AudioGainMode> & gainModeVec)279 ConversionResult<int> convertGainModeToAidl(const std::vector<ap_xsd::AudioGainMode>& gainModeVec) {
280 int gainModeMask = 0;
281 for (const ap_xsd::AudioGainMode& gainMode : gainModeVec) {
282 audio_gain_mode_t legacyGainMode;
283 if (::android::GainModeConverter::fromString(ap_xsd::toString(gainMode), legacyGainMode)) {
284 gainModeMask |= static_cast<int>(legacyGainMode);
285 }
286 }
287 return gainModeMask;
288 }
289
convertChannelMaskToAidl(const ap_xsd::AudioChannelMask & xChannelMask)290 ConversionResult<AudioChannelLayout> convertChannelMaskToAidl(
291 const ap_xsd::AudioChannelMask& xChannelMask) {
292 std::string xChannelMaskLiteral = ap_xsd::toString(xChannelMask);
293 audio_channel_mask_t legacyChannelMask = ::android::channelMaskFromString(xChannelMaskLiteral);
294 ConversionResult<AudioChannelLayout> result =
295 legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
296 legacyChannelMask,
297 /* isInput= */ xChannelMaskLiteral.find("AUDIO_CHANNEL_IN_") == 0);
298 if ((legacyChannelMask == AUDIO_CHANNEL_INVALID) || !result.ok()) {
299 LOG(ERROR) << __func__ << " Review Audio Policy config: " << xChannelMaskLiteral
300 << " is not a valid audio channel mask.";
301 return unexpected(BAD_VALUE);
302 }
303 return result;
304 }
305
convertGainToAidl(const ap_xsd::Gains::Gain & xGain)306 ConversionResult<AudioGain> convertGainToAidl(const ap_xsd::Gains::Gain& xGain) {
307 return AudioGain{
308 .mode = VALUE_OR_FATAL(convertGainModeToAidl(xGain.getMode())),
309 .channelMask =
310 xGain.hasChannel_mask()
311 ? VALUE_OR_FATAL(convertChannelMaskToAidl(xGain.getChannel_mask()))
312 : AudioChannelLayout{},
313 .minValue = xGain.hasMinValueMB() ? xGain.getMinValueMB() : 0,
314 .maxValue = xGain.hasMaxValueMB() ? xGain.getMaxValueMB() : 0,
315 .defaultValue = xGain.hasDefaultValueMB() ? xGain.getDefaultValueMB() : 0,
316 .stepValue = xGain.hasStepValueMB() ? xGain.getStepValueMB() : 0,
317 .minRampMs = xGain.hasMinRampMs() ? xGain.getMinRampMs() : 0,
318 .maxRampMs = xGain.hasMaxRampMs() ? xGain.getMaxRampMs() : 0,
319 .useForVolume = xGain.hasUseForVolume() ? xGain.getUseForVolume() : false,
320 };
321 }
322
convertAudioProfileToAidl(const ap_xsd::Profile & xProfile)323 ConversionResult<AudioProfile> convertAudioProfileToAidl(const ap_xsd::Profile& xProfile) {
324 return AudioProfile{
325 .format = xProfile.hasFormat()
326 ? VALUE_OR_FATAL(convertAudioFormatToAidl(xProfile.getFormat()))
327 : AudioFormatDescription{},
328 .channelMasks =
329 xProfile.hasChannelMasks()
330 ? VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::AudioChannelMask,
331 AudioChannelLayout>(
332 xProfile.getChannelMasks(), &convertChannelMaskToAidl)))
333 : std::vector<AudioChannelLayout>{},
334 .sampleRates = xProfile.hasSamplingRates()
335 ? VALUE_OR_FATAL((convertCollectionToAidl<int64_t, int>(
336 xProfile.getSamplingRates(),
337 [](const int64_t x) -> int { return x; })))
338 : std::vector<int>{}};
339 }
340
convertIoFlagsToAidl(const std::vector<ap_xsd::AudioInOutFlag> & flags,const ap_xsd::Role role,bool flagsForMixPort)341 ConversionResult<AudioIoFlags> convertIoFlagsToAidl(
342 const std::vector<ap_xsd::AudioInOutFlag>& flags, const ap_xsd::Role role,
343 bool flagsForMixPort) {
344 int legacyFlagMask = 0;
345 if ((role == ap_xsd::Role::sink && flagsForMixPort) ||
346 (role == ap_xsd::Role::source && !flagsForMixPort)) {
347 for (const ap_xsd::AudioInOutFlag& flag : flags) {
348 audio_input_flags_t legacyFlag;
349 if (::android::InputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
350 legacyFlagMask |= static_cast<int>(legacyFlag);
351 }
352 }
353 return AudioIoFlags::make<AudioIoFlags::Tag::input>(
354 VALUE_OR_FATAL(legacy2aidl_audio_input_flags_t_int32_t_mask(
355 static_cast<audio_input_flags_t>(legacyFlagMask))));
356 } else {
357 for (const ap_xsd::AudioInOutFlag& flag : flags) {
358 audio_output_flags_t legacyFlag;
359 if (::android::OutputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
360 legacyFlagMask |= static_cast<int>(legacyFlag);
361 }
362 }
363 return AudioIoFlags::make<AudioIoFlags::Tag::output>(
364 VALUE_OR_FATAL(legacy2aidl_audio_output_flags_t_int32_t_mask(
365 static_cast<audio_output_flags_t>(legacyFlagMask))));
366 }
367 }
368
convertDevicePortToAidl(const ap_xsd::DevicePorts::DevicePort & xDevicePort,const std::string & xDefaultOutputDevice,int32_t & nextPortId)369 ConversionResult<AudioPort> convertDevicePortToAidl(
370 const ap_xsd::DevicePorts::DevicePort& xDevicePort, const std::string& xDefaultOutputDevice,
371 int32_t& nextPortId) {
372 return AudioPort{
373 .id = nextPortId++,
374 .name = NON_EMPTY_STRING_OR_FATAL(xDevicePort.getTagName()),
375 .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>(
376 xDevicePort.getProfile(), convertAudioProfileToAidl))),
377 .flags = VALUE_OR_FATAL(convertIoFlagsToAidl({}, xDevicePort.getRole(), false)),
378 .gains = VALUE_OR_FATAL(
379 (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>(
380 xDevicePort.getGains(), &ap_xsd::Gains::getGain, convertGainToAidl))),
381
382 .ext = VALUE_OR_FATAL(createAudioPortExt(xDevicePort, xDefaultOutputDevice))};
383 }
384
convertDevicePortsInModuleToAidl(const ap_xsd::Modules::Module & xModuleConfig,int32_t & nextPortId)385 ConversionResult<std::vector<AudioPort>> convertDevicePortsInModuleToAidl(
386 const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) {
387 std::vector<AudioPort> audioPortVec;
388 std::vector<ap_xsd::DevicePorts> xDevicePortsVec = xModuleConfig.getDevicePorts();
389 if (xDevicePortsVec.size() > 1) {
390 LOG(ERROR) << __func__ << "Having multiple '<devicePorts>' elements is not allowed, found: "
391 << xDevicePortsVec.size();
392 return unexpected(BAD_VALUE);
393 }
394 if (!xDevicePortsVec.empty()) {
395 const std::string xDefaultOutputDevice = xModuleConfig.hasDefaultOutputDevice()
396 ? xModuleConfig.getDefaultOutputDevice()
397 : "";
398 audioPortVec.reserve(xDevicePortsVec[0].getDevicePort().size());
399 for (const ap_xsd::DevicePorts& xDevicePortsType : xDevicePortsVec) {
400 for (const ap_xsd::DevicePorts::DevicePort& xDevicePort :
401 xDevicePortsType.getDevicePort()) {
402 audioPortVec.push_back(VALUE_OR_FATAL(
403 convertDevicePortToAidl(xDevicePort, xDefaultOutputDevice, nextPortId)));
404 }
405 }
406 }
407 const std::unordered_set<std::string> xAttachedDeviceSet = getAttachedDevices(xModuleConfig);
408 for (const auto& port : audioPortVec) {
409 const auto& devicePort = port.ext.get<AudioPortExt::device>();
410 if (xAttachedDeviceSet.count(port.name) != devicePort.device.type.connection.empty()) {
411 LOG(ERROR) << __func__ << ": Review Audio Policy config: <attachedDevices> "
412 << "list is incorrect or devicePort \"" << port.name
413 << "\" type= " << devicePort.device.type.toString() << " is incorrect.";
414 return unexpected(BAD_VALUE);
415 }
416 }
417 return audioPortVec;
418 }
419
convertMixPortToAidl(const ap_xsd::MixPorts::MixPort & xMixPort,int32_t & nextPortId)420 ConversionResult<AudioPort> convertMixPortToAidl(const ap_xsd::MixPorts::MixPort& xMixPort,
421 int32_t& nextPortId) {
422 return AudioPort{
423 .id = nextPortId++,
424 .name = NON_EMPTY_STRING_OR_FATAL(xMixPort.getName()),
425 .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>(
426 xMixPort.getProfile(), convertAudioProfileToAidl))),
427 .flags = xMixPort.hasFlags()
428 ? VALUE_OR_FATAL(convertIoFlagsToAidl(xMixPort.getFlags(),
429 xMixPort.getRole(), true))
430 : VALUE_OR_FATAL(convertIoFlagsToAidl({}, xMixPort.getRole(), true)),
431 .gains = VALUE_OR_FATAL(
432 (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>(
433 xMixPort.getGains(), &ap_xsd::Gains::getGain, &convertGainToAidl))),
434 .ext = VALUE_OR_FATAL(createAudioPortExt(xMixPort)),
435 };
436 }
437
convertMixPortsInModuleToAidl(const ap_xsd::Modules::Module & xModuleConfig,int32_t & nextPortId)438 ConversionResult<std::vector<AudioPort>> convertMixPortsInModuleToAidl(
439 const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) {
440 std::vector<AudioPort> audioPortVec;
441 std::vector<ap_xsd::MixPorts> xMixPortsVec = xModuleConfig.getMixPorts();
442 if (xMixPortsVec.size() > 1) {
443 LOG(ERROR) << __func__ << "Having multiple '<mixPorts>' elements is not allowed, found: "
444 << xMixPortsVec.size();
445 return unexpected(BAD_VALUE);
446 }
447 if (!xMixPortsVec.empty()) {
448 audioPortVec.reserve(xMixPortsVec[0].getMixPort().size());
449 for (const ap_xsd::MixPorts& xMixPortsType : xMixPortsVec) {
450 for (const ap_xsd::MixPorts::MixPort& xMixPort : xMixPortsType.getMixPort()) {
451 audioPortVec.push_back(VALUE_OR_FATAL(convertMixPortToAidl(xMixPort, nextPortId)));
452 }
453 }
454 }
455 return audioPortVec;
456 }
457
getSinkPortId(const ap_xsd::Routes::Route & xRoute,const std::unordered_map<std::string,int32_t> & portMap)458 ConversionResult<int32_t> getSinkPortId(const ap_xsd::Routes::Route& xRoute,
459 const std::unordered_map<std::string, int32_t>& portMap) {
460 auto portMapIter = portMap.find(xRoute.getSink());
461 if (portMapIter == portMap.end()) {
462 LOG(ERROR) << __func__ << " Review Audio Policy config: audio route"
463 << "has sink: " << xRoute.getSink()
464 << " which is neither a device port nor mix port.";
465 return unexpected(BAD_VALUE);
466 }
467 return portMapIter->second;
468 }
469
getSourcePortIds(const ap_xsd::Routes::Route & xRoute,const std::unordered_map<std::string,int32_t> & portMap)470 ConversionResult<std::vector<int32_t>> getSourcePortIds(
471 const ap_xsd::Routes::Route& xRoute,
472 const std::unordered_map<std::string, int32_t>& portMap) {
473 std::vector<int32_t> sourcePortIds;
474 for (const std::string& rawSource : ::android::base::Split(xRoute.getSources(), ",")) {
475 const std::string source = ::android::base::Trim(rawSource);
476 auto portMapIter = portMap.find(source);
477 if (portMapIter == portMap.end()) {
478 LOG(ERROR) << __func__ << " Review Audio Policy config: audio route"
479 << "has source \"" << source
480 << "\" which is neither a device port nor mix port.";
481 return unexpected(BAD_VALUE);
482 }
483 sourcePortIds.push_back(portMapIter->second);
484 }
485 return sourcePortIds;
486 }
487
convertRouteToAidl(const ap_xsd::Routes::Route & xRoute,const std::vector<AudioPort> & aidlAudioPorts)488 ConversionResult<AudioRoute> convertRouteToAidl(const ap_xsd::Routes::Route& xRoute,
489 const std::vector<AudioPort>& aidlAudioPorts) {
490 std::unordered_map<std::string, int32_t> portMap;
491 for (const AudioPort& port : aidlAudioPorts) {
492 portMap.insert({port.name, port.id});
493 }
494 return AudioRoute{.sourcePortIds = VALUE_OR_FATAL(getSourcePortIds(xRoute, portMap)),
495 .sinkPortId = VALUE_OR_FATAL(getSinkPortId(xRoute, portMap)),
496 .isExclusive = (xRoute.getType() == ap_xsd::MixType::mux)};
497 }
498
convertRoutesInModuleToAidl(const ap_xsd::Modules::Module & xModuleConfig,const std::vector<AudioPort> & aidlAudioPorts)499 ConversionResult<std::vector<AudioRoute>> convertRoutesInModuleToAidl(
500 const ap_xsd::Modules::Module& xModuleConfig,
501 const std::vector<AudioPort>& aidlAudioPorts) {
502 std::vector<AudioRoute> audioRouteVec;
503 std::vector<ap_xsd::Routes> xRoutesVec = xModuleConfig.getRoutes();
504 if (!xRoutesVec.empty()) {
505 /*
506 * xRoutesVec likely only contains one element; that is, it's
507 * likely that all ap_xsd::Routes::MixPort types that we need to convert
508 * are inside of xRoutesVec[0].
509 */
510 audioRouteVec.reserve(xRoutesVec[0].getRoute().size());
511 for (const ap_xsd::Routes& xRoutesType : xRoutesVec) {
512 for (const ap_xsd::Routes::Route& xRoute : xRoutesType.getRoute()) {
513 audioRouteVec.push_back(VALUE_OR_FATAL(convertRouteToAidl(xRoute, aidlAudioPorts)));
514 }
515 }
516 }
517 return audioRouteVec;
518 }
519
convertModuleConfigToAidl(const ap_xsd::Modules::Module & xModuleConfig)520 ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
521 const ap_xsd::Modules::Module& xModuleConfig) {
522 auto result = std::make_unique<Module::Configuration>();
523 auto& aidlModuleConfig = *result;
524 std::vector<AudioPort> devicePorts = VALUE_OR_FATAL(
525 convertDevicePortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId));
526
527 // The XML config does not specify the default input device.
528 // Assign the first attached input device as the default.
529 for (auto& port : devicePorts) {
530 if (port.flags.getTag() != AudioIoFlags::input) continue;
531 auto& deviceExt = port.ext.get<AudioPortExt::device>();
532 if (!deviceExt.device.type.connection.empty()) continue;
533 deviceExt.flags |= 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
534 break;
535 }
536
537 std::vector<AudioPort> mixPorts = VALUE_OR_FATAL(
538 convertMixPortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId));
539 aidlModuleConfig.ports.reserve(devicePorts.size() + mixPorts.size());
540 aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), devicePorts.begin(),
541 devicePorts.end());
542 aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), mixPorts.begin(), mixPorts.end());
543
544 aidlModuleConfig.routes =
545 VALUE_OR_FATAL(convertRoutesInModuleToAidl(xModuleConfig, aidlModuleConfig.ports));
546 return result;
547 }
548
convertTelephonyModeToAidl(const std::string & xsdcModeCriterionType)549 ConversionResult<AudioMode> convertTelephonyModeToAidl(const std::string& xsdcModeCriterionType) {
550 const auto it = std::find_if(kValidAudioModes.begin(), kValidAudioModes.end(),
551 [&xsdcModeCriterionType](const auto& mode) {
552 return toString(mode) == xsdcModeCriterionType;
553 });
554 if (it == kValidAudioModes.end()) {
555 LOG(ERROR) << __func__ << " invalid mode " << xsdcModeCriterionType;
556 return unexpected(BAD_VALUE);
557 }
558 return *it;
559 }
560
convertDeviceAddressToAidl(const std::string & xsdcAddress)561 ConversionResult<AudioDeviceAddress> convertDeviceAddressToAidl(const std::string& xsdcAddress) {
562 return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcAddress);
563 }
564
getCriterionTypeByName(const std::string & name,const std::vector<eng_xsd::CriterionTypesType> & xsdcCriterionTypesVec)565 ConversionResult<eng_xsd::CriterionTypeType> getCriterionTypeByName(
566 const std::string& name,
567 const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
568 for (const auto& xsdCriterionTypes : xsdcCriterionTypesVec) {
569 for (const auto& xsdcCriterionType : xsdCriterionTypes.getCriterion_type()) {
570 if (xsdcCriterionType.getName() == name) {
571 return xsdcCriterionType;
572 }
573 }
574 }
575 LOG(ERROR) << __func__ << " failed to find criterion type " << name;
576 return unexpected(BAD_VALUE);
577 }
578
579 ConversionResult<std::vector<std::optional<AudioHalCapCriterionV2>>>
convertCapCriteriaCollectionToAidl(const std::vector<eng_xsd::CriteriaType> & xsdcCriteriaVec,const std::vector<eng_xsd::CriterionTypesType> & xsdcCriterionTypesVec)580 convertCapCriteriaCollectionToAidl(
581 const std::vector<eng_xsd::CriteriaType>& xsdcCriteriaVec,
582 const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
583 std::vector<std::optional<AudioHalCapCriterionV2>> resultAidlCriterionVec;
584 if (xsdcCriteriaVec.empty() || xsdcCriterionTypesVec.empty()) {
585 LOG(ERROR) << __func__ << " empty criteria/criterionTypes";
586 return unexpected(BAD_VALUE);
587 }
588 for (const auto& xsdCriteria : xsdcCriteriaVec) {
589 for (const auto& xsdcCriterion : xsdCriteria.getCriterion()) {
590 resultAidlCriterionVec.push_back(
591 std::optional<AudioHalCapCriterionV2>(VALUE_OR_FATAL(
592 convertCapCriterionV2ToAidl(xsdcCriterion, xsdcCriterionTypesVec))));
593 }
594 }
595 return resultAidlCriterionVec;
596 }
597
convertDevicesToAidl(const eng_xsd::CriterionTypeType & xsdcDeviceCriterionType)598 ConversionResult<std::vector<AudioDeviceDescription>> convertDevicesToAidl(
599 const eng_xsd::CriterionTypeType& xsdcDeviceCriterionType) {
600 if (xsdcDeviceCriterionType.getValues().empty()) {
601 LOG(ERROR) << __func__ << " no values provided";
602 return unexpected(BAD_VALUE);
603 }
604 std::vector<AudioDeviceDescription> aidlDevices;
605 for (eng_xsd::ValuesType xsdcValues : xsdcDeviceCriterionType.getValues()) {
606 aidlDevices.reserve(xsdcValues.getValue().size());
607 for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
608 if (!xsdcValue.hasAndroid_type()) {
609 LOG(ERROR) << __func__ << " empty android type";
610 return unexpected(BAD_VALUE);
611 }
612 uint32_t integerValue;
613 if (!convertTo(xsdcValue.getAndroid_type(), integerValue)) {
614 LOG(ERROR) << __func__ << " failed to convert android type "
615 << xsdcValue.getAndroid_type();
616 return unexpected(BAD_VALUE);
617 }
618 aidlDevices.push_back(
619 VALUE_OR_RETURN(legacy2aidl_audio_devices_t_AudioDeviceDescription(
620 static_cast<audio_devices_t>(integerValue))));
621 }
622 }
623 return aidlDevices;
624 }
625
convertDeviceAddressesToAidl(const eng_xsd::CriterionTypeType & xsdcDeviceAddressesCriterionType)626 ConversionResult<std::vector<AudioDeviceAddress>> convertDeviceAddressesToAidl(
627 const eng_xsd::CriterionTypeType& xsdcDeviceAddressesCriterionType) {
628 if (xsdcDeviceAddressesCriterionType.getValues().empty()) {
629 LOG(ERROR) << __func__ << " no values provided";
630 return unexpected(BAD_VALUE);
631 }
632 std::vector<AudioDeviceAddress> aidlDeviceAddresses;
633 for (eng_xsd::ValuesType xsdcValues : xsdcDeviceAddressesCriterionType.getValues()) {
634 aidlDeviceAddresses.reserve(xsdcValues.getValue().size());
635 for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
636 aidlDeviceAddresses.push_back(
637 AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcValue.getLiteral()));
638 }
639 }
640 return aidlDeviceAddresses;
641 }
642
convertAudioModeToAidl(const std::string & xsdcAudioModeType)643 ConversionResult<AudioMode> convertAudioModeToAidl(const std::string& xsdcAudioModeType) {
644 const auto it = std::find_if(enum_range<AudioMode>().begin(), enum_range<AudioMode>().end(),
645 [&](const auto v) { return toString(v) == xsdcAudioModeType; });
646 if (it == enum_range<AudioMode>().end()) {
647 LOG(ERROR) << __func__ << " invalid audio mode " << xsdcAudioModeType;
648 return unexpected(BAD_VALUE);
649 }
650 return *it;
651 }
652
convertTelephonyModesToAidl(const eng_xsd::CriterionTypeType & xsdcTelephonyModeCriterionType)653 ConversionResult<std::vector<AudioMode>> convertTelephonyModesToAidl(
654 const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) {
655 if (xsdcTelephonyModeCriterionType.getValues().empty()) {
656 LOG(ERROR) << __func__ << " no values provided";
657 return unexpected(BAD_VALUE);
658 }
659 std::vector<AudioMode> aidlAudioModes;
660 for (eng_xsd::ValuesType xsdcValues : xsdcTelephonyModeCriterionType.getValues()) {
661 aidlAudioModes.reserve(xsdcValues.getValue().size());
662 for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
663 aidlAudioModes.push_back(
664 VALUE_OR_RETURN(convertAudioModeToAidl(xsdcValue.getLiteral())));
665 }
666 }
667 return aidlAudioModes;
668 }
669
convertForceUseConfigsToAidl(const std::string & criterionValue,const eng_xsd::CriterionTypeType & xsdcForcedConfigCriterionType)670 ConversionResult<std::vector<AudioPolicyForceUse>> convertForceUseConfigsToAidl(
671 const std::string& criterionValue,
672 const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
673 if (xsdcForcedConfigCriterionType.getValues().empty()) {
674 LOG(ERROR) << __func__ << " no values provided";
675 return unexpected(BAD_VALUE);
676 }
677 std::vector<AudioPolicyForceUse> aidlForcedConfigs;
678 for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) {
679 aidlForcedConfigs.reserve(xsdcValues.getValue().size());
680 for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
681 aidlForcedConfigs.push_back(
682 VALUE_OR_RETURN(convertForceUseToAidl(criterionValue, xsdcValue.getLiteral())));
683 }
684 }
685 return aidlForcedConfigs;
686 }
687
688 template <typename T>
convertForceUseForcedConfigToAidl(const std::string & xsdcForcedConfigCriterionType)689 ConversionResult<T> convertForceUseForcedConfigToAidl(
690 const std::string& xsdcForcedConfigCriterionType) {
691 const auto it = std::find_if(enum_range<T>().begin(), enum_range<T>().end(), [&](const auto v) {
692 return toString(v) == xsdcForcedConfigCriterionType;
693 });
694 if (it == enum_range<T>().end()) {
695 LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType;
696 return unexpected(BAD_VALUE);
697 }
698 return *it;
699 }
700
convertForceUseToAidl(const std::string & xsdcCriterionName,const std::string & xsdcCriterionValue)701 ConversionResult<AudioPolicyForceUse> convertForceUseToAidl(const std::string& xsdcCriterionName,
702 const std::string& xsdcCriterionValue) {
703 if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
704 strlen(kXsdcForceConfigForCommunication))) {
705 const auto deviceCategory = VALUE_OR_RETURN(
706 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
707 xsdcCriterionValue));
708 return AudioPolicyForceUse::make<AudioPolicyForceUse::forCommunication>(deviceCategory);
709 }
710 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
711 strlen(kXsdcForceConfigForMedia))) {
712 const auto deviceCategory = VALUE_OR_RETURN(
713 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::MediaDeviceCategory>(
714 xsdcCriterionValue));
715 return AudioPolicyForceUse::make<AudioPolicyForceUse::forMedia>(deviceCategory);
716 }
717 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
718 strlen(kXsdcForceConfigForRecord))) {
719 const auto deviceCategory = VALUE_OR_RETURN(
720 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
721 xsdcCriterionValue));
722 return AudioPolicyForceUse::make<AudioPolicyForceUse::forRecord>(deviceCategory);
723 }
724 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
725 strlen(kXsdcForceConfigForDock))) {
726 const auto dockType =
727 VALUE_OR_RETURN(convertForceUseForcedConfigToAidl<AudioPolicyForceUse::DockType>(
728 xsdcCriterionValue));
729 return AudioPolicyForceUse::make<AudioPolicyForceUse::dock>(dockType);
730 }
731 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
732 strlen(kXsdcForceConfigForSystem))) {
733 return AudioPolicyForceUse::make<AudioPolicyForceUse::systemSounds>(xsdcCriterionValue ==
734 "SYSTEM_ENFORCED");
735 }
736 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
737 strlen(kXsdcForceConfigForHdmiSystemAudio))) {
738 return AudioPolicyForceUse::make<AudioPolicyForceUse::hdmiSystemAudio>(
739 xsdcCriterionValue == "HDMI_SYSTEM_AUDIO_ENFORCED");
740 }
741 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
742 strlen(kXsdcForceConfigForEncodedSurround))) {
743 const auto encodedSurround = VALUE_OR_RETURN(
744 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::EncodedSurroundConfig>(
745 xsdcCriterionValue));
746 return AudioPolicyForceUse::make<AudioPolicyForceUse::encodedSurround>(encodedSurround);
747 }
748 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
749 strlen(kXsdcForceConfigForVibrateRinging))) {
750 const auto deviceCategory = VALUE_OR_RETURN(
751 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
752 xsdcCriterionValue));
753 return AudioPolicyForceUse::make<AudioPolicyForceUse::forVibrateRinging>(deviceCategory);
754 }
755 LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
756 return unexpected(BAD_VALUE);
757 }
758
convertCapCriterionV2ToAidl(const eng_xsd::CriterionType & xsdcCriterion,const std::vector<eng_xsd::CriterionTypesType> & xsdcCriterionTypesVec)759 ConversionResult<AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
760 const eng_xsd::CriterionType& xsdcCriterion,
761 const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
762 eng_xsd::CriterionTypeType xsdcCriterionType =
763 VALUE_OR_RETURN(getCriterionTypeByName(xsdcCriterion.getType(), xsdcCriterionTypesVec));
764 std::string defaultLiteralValue =
765 xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
766 using Tag = AudioHalCapCriterionV2::Tag;
767 if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevices))) {
768 return AudioHalCapCriterionV2::make<Tag::availableInputDevices>(
769 VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
770 }
771 if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevices))) {
772 return AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(
773 VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
774 }
775 if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevicesAddresses))) {
776 return AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(
777 VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
778 }
779 if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevicesAddresses))) {
780 return AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(
781 VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
782 }
783 if (iequals(xsdcCriterion.getName(), toString(Tag::telephonyMode))) {
784 return AudioHalCapCriterionV2::make<Tag::telephonyMode>(
785 VALUE_OR_RETURN(convertTelephonyModesToAidl(xsdcCriterionType)));
786 }
787 if (!fastcmp<strncmp>(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse,
788 strlen(kXsdcForceConfigForUse))) {
789 return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(VALUE_OR_RETURN(
790 convertForceUseConfigsToAidl(xsdcCriterion.getName(), xsdcCriterionType)));
791 }
792 LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
793 return unexpected(BAD_VALUE);
794 }
795
convertCapCriterionToAidl(const eng_xsd::CriterionType & xsdcCriterion)796 ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl(
797 const eng_xsd::CriterionType& xsdcCriterion) {
798 AudioHalCapCriterion aidlCapCriterion;
799 aidlCapCriterion.name = xsdcCriterion.getName();
800 aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
801 aidlCapCriterion.defaultLiteralValue =
802 xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
803 return aidlCapCriterion;
804 }
805
convertCurvePointToAidl(const std::string & xsdcCurvePoint)806 ConversionResult<AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
807 const std::string& xsdcCurvePoint) {
808 AudioHalVolumeCurve::CurvePoint aidlCurvePoint{};
809 if ((sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index,
810 &aidlCurvePoint.attenuationMb) != 2) ||
811 (aidlCurvePoint.index < AudioHalVolumeCurve::CurvePoint::MIN_INDEX) ||
812 (aidlCurvePoint.index > AudioHalVolumeCurve::CurvePoint::MAX_INDEX)) {
813 LOG(ERROR) << __func__ << " Review Audio Policy config: volume curve point:"
814 << "\"" << xsdcCurvePoint << "\" is invalid";
815 return unexpected(BAD_VALUE);
816 }
817 return aidlCurvePoint;
818 }
819 } // namespace aidl::android::hardware::audio::core::internal
820