blob: 584590362a2f47cfba49500bd63c19494e9a22b9 [file] [log] [blame]
Mikhail Naganov206ad4d2024-11-20 21:17:52 +00001/*
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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000017#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>
Mikhail Naganov206ad4d2024-11-20 21:17:52 +000024#include <android/binder_enums.h>
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000025
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>
François Gaffie57ccab72024-04-17 11:47:51 +020030#include <media/convert.h>
31#include <utils/FastStrcmp.h>
32
33#include <Utils.h>
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000034
35#include "core-impl/XmlConverter.h"
36#include "core-impl/XsdcConversion.h"
37
François Gaffie57ccab72024-04-17 11:47:51 +020038using aidl::android::hardware::audio::common::iequals;
39using aidl::android::hardware::audio::common::isValidAudioMode;
François Gaffie57ccab72024-04-17 11:47:51 +020040using aidl::android::hardware::audio::common::kValidAudioModes;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000041using aidl::android::media::audio::common::AudioChannelLayout;
François Gaffie57ccab72024-04-17 11:47:51 +020042using aidl::android::media::audio::common::AudioContentType;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000043using aidl::android::media::audio::common::AudioDevice;
44using aidl::android::media::audio::common::AudioDeviceAddress;
45using aidl::android::media::audio::common::AudioDeviceDescription;
46using aidl::android::media::audio::common::AudioDeviceType;
47using aidl::android::media::audio::common::AudioFormatDescription;
48using aidl::android::media::audio::common::AudioFormatType;
49using aidl::android::media::audio::common::AudioGain;
50using aidl::android::media::audio::common::AudioHalCapCriterion;
51using aidl::android::media::audio::common::AudioHalCapCriterionType;
François Gaffie57ccab72024-04-17 11:47:51 +020052using aidl::android::media::audio::common::AudioHalCapCriterionV2;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000053using aidl::android::media::audio::common::AudioHalVolumeCurve;
54using aidl::android::media::audio::common::AudioIoFlags;
François Gaffie57ccab72024-04-17 11:47:51 +020055using aidl::android::media::audio::common::AudioMode;
François Gaffie57ccab72024-04-17 11:47:51 +020056using aidl::android::media::audio::common::AudioPolicyForceUse;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000057using aidl::android::media::audio::common::AudioPort;
58using aidl::android::media::audio::common::AudioPortConfig;
59using aidl::android::media::audio::common::AudioPortDeviceExt;
60using aidl::android::media::audio::common::AudioPortExt;
61using aidl::android::media::audio::common::AudioPortMixExt;
62using aidl::android::media::audio::common::AudioProfile;
François Gaffie57ccab72024-04-17 11:47:51 +020063using aidl::android::media::audio::common::AudioSource;
64using aidl::android::media::audio::common::AudioStreamType;
65using aidl::android::media::audio::common::AudioUsage;
Mikhail Naganov206ad4d2024-11-20 21:17:52 +000066using android::BAD_VALUE;
67using android::base::unexpected;
68using android::utilities::convertTo;
69using ndk::enum_range;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000070
71namespace ap_xsd = android::audio::policy::configuration;
72namespace eng_xsd = android::audio::policy::engine::configuration;
73
74namespace aidl::android::hardware::audio::core::internal {
75
François Gaffie57ccab72024-04-17 11:47:51 +020076static constexpr const char kXsdcForceConfigForCommunication[] = "ForceUseForCommunication";
77static constexpr const char kXsdcForceConfigForMedia[] = "ForceUseForMedia";
78static constexpr const char kXsdcForceConfigForRecord[] = "ForceUseForRecord";
79static constexpr const char kXsdcForceConfigForDock[] = "ForceUseForDock";
80static constexpr const char kXsdcForceConfigForSystem[] = "ForceUseForSystem";
81static constexpr const char kXsdcForceConfigForHdmiSystemAudio[] = "ForceUseForHdmiSystemAudio";
82static constexpr const char kXsdcForceConfigForEncodedSurround[] = "ForceUseForEncodedSurround";
83static constexpr const char kXsdcForceConfigForVibrateRinging[] = "ForceUseForVibrateRinging";
84
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +000085inline 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
François Gaffie57ccab72024-04-17 11:47:51 +020096ConversionResult<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
121ConversionResult<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
139ConversionResult<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
157ConversionResult<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
176ConversionResult<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
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000190ConversionResult<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
203std::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
216ConversionResult<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
229ConversionResult<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
246ConversionResult<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
265ConversionResult<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
279ConversionResult<int> convertGainModeToAidl(const std::vector<ap_xsd::AudioGainMode>& gainModeVec) {
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000280 int gainModeMask = 0;
281 for (const ap_xsd::AudioGainMode& gainMode : gainModeVec) {
Mikhail Naganovcc21b6f2023-10-17 19:39:27 -0700282 audio_gain_mode_t legacyGainMode;
283 if (::android::GainModeConverter::fromString(ap_xsd::toString(gainMode), legacyGainMode)) {
284 gainModeMask |= static_cast<int>(legacyGainMode);
285 }
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000286 }
287 return gainModeMask;
288}
289
290ConversionResult<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
306ConversionResult<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
323ConversionResult<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
341ConversionResult<AudioIoFlags> convertIoFlagsToAidl(
342 const std::vector<ap_xsd::AudioInOutFlag>& flags, const ap_xsd::Role role,
343 bool flagsForMixPort) {
Mikhail Naganov37fe9e82023-11-28 17:07:23 -0800344 int legacyFlagMask = 0;
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000345 if ((role == ap_xsd::Role::sink && flagsForMixPort) ||
346 (role == ap_xsd::Role::source && !flagsForMixPort)) {
347 for (const ap_xsd::AudioInOutFlag& flag : flags) {
Mikhail Naganovcc21b6f2023-10-17 19:39:27 -0700348 audio_input_flags_t legacyFlag;
349 if (::android::InputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
Mikhail Naganov37fe9e82023-11-28 17:07:23 -0800350 legacyFlagMask |= static_cast<int>(legacyFlag);
Mikhail Naganovcc21b6f2023-10-17 19:39:27 -0700351 }
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000352 }
Mikhail Naganov37fe9e82023-11-28 17:07:23 -0800353 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))));
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000356 } else {
357 for (const ap_xsd::AudioInOutFlag& flag : flags) {
Mikhail Naganovcc21b6f2023-10-17 19:39:27 -0700358 audio_output_flags_t legacyFlag;
359 if (::android::OutputFlagConverter::fromString(ap_xsd::toString(flag), legacyFlag)) {
Mikhail Naganov37fe9e82023-11-28 17:07:23 -0800360 legacyFlagMask |= static_cast<int>(legacyFlag);
Mikhail Naganovcc21b6f2023-10-17 19:39:27 -0700361 }
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000362 }
Mikhail Naganov37fe9e82023-11-28 17:07:23 -0800363 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))));
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000366 }
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000367}
368
369ConversionResult<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
385ConversionResult<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
420ConversionResult<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
438ConversionResult<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
458ConversionResult<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
470ConversionResult<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
488ConversionResult<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
499ConversionResult<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
520ConversionResult<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
François Gaffie57ccab72024-04-17 11:47:51 +0200549ConversionResult<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
561ConversionResult<AudioDeviceAddress> convertDeviceAddressToAidl(const std::string& xsdcAddress) {
562 return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcAddress);
563}
564
565ConversionResult<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
579ConversionResult<std::vector<std::optional<AudioHalCapCriterionV2>>>
580convertCapCriteriaCollectionToAidl(
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
598ConversionResult<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
626ConversionResult<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
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000643ConversionResult<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
François Gaffie57ccab72024-04-17 11:47:51 +0200653ConversionResult<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()) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000663 aidlAudioModes.push_back(
664 VALUE_OR_RETURN(convertAudioModeToAidl(xsdcValue.getLiteral())));
François Gaffie57ccab72024-04-17 11:47:51 +0200665 }
666 }
667 return aidlAudioModes;
668}
669
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000670ConversionResult<std::vector<AudioPolicyForceUse>> convertForceUseConfigsToAidl(
671 const std::string& criterionValue,
François Gaffie57ccab72024-04-17 11:47:51 +0200672 const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
673 if (xsdcForcedConfigCriterionType.getValues().empty()) {
674 LOG(ERROR) << __func__ << " no values provided";
675 return unexpected(BAD_VALUE);
676 }
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000677 std::vector<AudioPolicyForceUse> aidlForcedConfigs;
François Gaffie57ccab72024-04-17 11:47:51 +0200678 for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) {
679 aidlForcedConfigs.reserve(xsdcValues.getValue().size());
680 for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000681 aidlForcedConfigs.push_back(
682 VALUE_OR_RETURN(convertForceUseToAidl(criterionValue, xsdcValue.getLiteral())));
François Gaffie57ccab72024-04-17 11:47:51 +0200683 }
684 }
685 return aidlForcedConfigs;
686}
687
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000688template <typename T>
689ConversionResult<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
701ConversionResult<AudioPolicyForceUse> convertForceUseToAidl(const std::string& xsdcCriterionName,
702 const std::string& xsdcCriterionValue) {
François Gaffie57ccab72024-04-17 11:47:51 +0200703 if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000704 strlen(kXsdcForceConfigForCommunication))) {
705 const auto deviceCategory = VALUE_OR_RETURN(
706 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
707 xsdcCriterionValue));
708 return AudioPolicyForceUse::make<AudioPolicyForceUse::forCommunication>(deviceCategory);
François Gaffie57ccab72024-04-17 11:47:51 +0200709 }
710 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
711 strlen(kXsdcForceConfigForMedia))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000712 const auto deviceCategory = VALUE_OR_RETURN(
713 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::MediaDeviceCategory>(
714 xsdcCriterionValue));
715 return AudioPolicyForceUse::make<AudioPolicyForceUse::forMedia>(deviceCategory);
François Gaffie57ccab72024-04-17 11:47:51 +0200716 }
717 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
718 strlen(kXsdcForceConfigForRecord))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000719 const auto deviceCategory = VALUE_OR_RETURN(
720 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
721 xsdcCriterionValue));
722 return AudioPolicyForceUse::make<AudioPolicyForceUse::forRecord>(deviceCategory);
François Gaffie57ccab72024-04-17 11:47:51 +0200723 }
724 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000725 strlen(kXsdcForceConfigForDock))) {
726 const auto dockType =
727 VALUE_OR_RETURN(convertForceUseForcedConfigToAidl<AudioPolicyForceUse::DockType>(
728 xsdcCriterionValue));
729 return AudioPolicyForceUse::make<AudioPolicyForceUse::dock>(dockType);
François Gaffie57ccab72024-04-17 11:47:51 +0200730 }
731 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
732 strlen(kXsdcForceConfigForSystem))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000733 return AudioPolicyForceUse::make<AudioPolicyForceUse::systemSounds>(xsdcCriterionValue ==
734 "SYSTEM_ENFORCED");
François Gaffie57ccab72024-04-17 11:47:51 +0200735 }
736 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
737 strlen(kXsdcForceConfigForHdmiSystemAudio))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000738 return AudioPolicyForceUse::make<AudioPolicyForceUse::hdmiSystemAudio>(
739 xsdcCriterionValue == "HDMI_SYSTEM_AUDIO_ENFORCED");
François Gaffie57ccab72024-04-17 11:47:51 +0200740 }
741 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
742 strlen(kXsdcForceConfigForEncodedSurround))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000743 const auto encodedSurround = VALUE_OR_RETURN(
744 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::EncodedSurroundConfig>(
745 xsdcCriterionValue));
746 return AudioPolicyForceUse::make<AudioPolicyForceUse::encodedSurround>(encodedSurround);
François Gaffie57ccab72024-04-17 11:47:51 +0200747 }
748 if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
749 strlen(kXsdcForceConfigForVibrateRinging))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000750 const auto deviceCategory = VALUE_OR_RETURN(
751 convertForceUseForcedConfigToAidl<AudioPolicyForceUse::CommunicationDeviceCategory>(
752 xsdcCriterionValue));
753 return AudioPolicyForceUse::make<AudioPolicyForceUse::forVibrateRinging>(deviceCategory);
François Gaffie57ccab72024-04-17 11:47:51 +0200754 }
755 LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
756 return unexpected(BAD_VALUE);
757}
758
759ConversionResult<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))) {
Mikhail Naganov206ad4d2024-11-20 21:17:52 +0000789 return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(VALUE_OR_RETURN(
790 convertForceUseConfigsToAidl(xsdcCriterion.getName(), xsdcCriterionType)));
François Gaffie57ccab72024-04-17 11:47:51 +0200791 }
792 LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
793 return unexpected(BAD_VALUE);
794}
795
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000796ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl(
797 const eng_xsd::CriterionType& xsdcCriterion) {
798 AudioHalCapCriterion aidlCapCriterion;
799 aidlCapCriterion.name = xsdcCriterion.getName();
800 aidlCapCriterion.criterionTypeName = xsdcCriterion.getType();
François Gaffie57ccab72024-04-17 11:47:51 +0200801 aidlCapCriterion.defaultLiteralValue =
802 xsdcCriterion.has_default() ? xsdcCriterion.get_default() : "";
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000803 return aidlCapCriterion;
804}
805
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000806ConversionResult<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}
François Gaffie460bd6d2025-01-17 14:33:30 +0100819
820/**
821 * The hard coded id must be in sync with policy.h definition of legacy strategy ids.
822 */
823std::unordered_map<std::string, int> getLegacyProductStrategyMap() {
824#define STRATEGY_ENTRY(name, id) {"STRATEGY_" #name, static_cast<int>(id)}
825
826 return {STRATEGY_ENTRY(MEDIA, 5),
827 STRATEGY_ENTRY(PHONE, 0),
828 STRATEGY_ENTRY(SONIFICATION, 1),
829 STRATEGY_ENTRY(SONIFICATION_RESPECTFUL, 4),
830 STRATEGY_ENTRY(DTMF, 6),
831 STRATEGY_ENTRY(ENFORCED_AUDIBLE, 2),
832 STRATEGY_ENTRY(CALL_ASSISTANT, 7),
833 STRATEGY_ENTRY(TRANSMITTED_THROUGH_SPEAKER,8),
834 STRATEGY_ENTRY(ACCESSIBILITY, 3)};
835#undef STRATEGY_ENTRY
836}
837
Lorena Torres-Huerta394e2522022-12-20 02:21:41 +0000838} // namespace aidl::android::hardware::audio::core::internal