xref: /aosp_15_r20/hardware/interfaces/audio/aidl/default/XsdcConversion.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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