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