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> |
| 13 | |
| 14 | #include "core-impl/XmlConverter.h" |
| 15 | #include "core-impl/XsdcConversion.h" |
| 16 | |
| 17 | using aidl::android::media::audio::common::AudioChannelLayout; |
| 18 | using aidl::android::media::audio::common::AudioDevice; |
| 19 | using aidl::android::media::audio::common::AudioDeviceAddress; |
| 20 | using aidl::android::media::audio::common::AudioDeviceDescription; |
| 21 | using aidl::android::media::audio::common::AudioDeviceType; |
| 22 | using aidl::android::media::audio::common::AudioFormatDescription; |
| 23 | using aidl::android::media::audio::common::AudioFormatType; |
| 24 | using aidl::android::media::audio::common::AudioGain; |
| 25 | using aidl::android::media::audio::common::AudioHalCapCriterion; |
| 26 | using aidl::android::media::audio::common::AudioHalCapCriterionType; |
| 27 | using aidl::android::media::audio::common::AudioHalVolumeCurve; |
| 28 | using aidl::android::media::audio::common::AudioIoFlags; |
| 29 | using aidl::android::media::audio::common::AudioPort; |
| 30 | using aidl::android::media::audio::common::AudioPortConfig; |
| 31 | using aidl::android::media::audio::common::AudioPortDeviceExt; |
| 32 | using aidl::android::media::audio::common::AudioPortExt; |
| 33 | using aidl::android::media::audio::common::AudioPortMixExt; |
| 34 | using aidl::android::media::audio::common::AudioProfile; |
| 35 | using ::android::BAD_VALUE; |
| 36 | using ::android::base::unexpected; |
| 37 | |
| 38 | namespace ap_xsd = android::audio::policy::configuration; |
| 39 | namespace eng_xsd = android::audio::policy::engine::configuration; |
| 40 | |
| 41 | namespace aidl::android::hardware::audio::core::internal { |
| 42 | |
| 43 | inline ConversionResult<std::string> assertNonEmpty(const std::string& s) { |
| 44 | if (s.empty()) { |
| 45 | LOG(ERROR) << __func__ << " Review Audio Policy config: " |
| 46 | << " empty string is not valid."; |
| 47 | return unexpected(BAD_VALUE); |
| 48 | } |
| 49 | return s; |
| 50 | } |
| 51 | |
| 52 | #define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s)) |
| 53 | |
| 54 | ConversionResult<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) { |
| 55 | audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT); |
| 56 | ConversionResult<AudioFormatDescription> result = |
| 57 | legacy2aidl_audio_format_t_AudioFormatDescription(legacyFormat); |
| 58 | if ((legacyFormat == AUDIO_FORMAT_DEFAULT && xsdcFormat.compare("AUDIO_FORMAT_DEFAULT") != 0) || |
| 59 | !result.ok()) { |
| 60 | LOG(ERROR) << __func__ << " Review Audio Policy config: " << xsdcFormat |
| 61 | << " is not a valid audio format."; |
| 62 | return unexpected(BAD_VALUE); |
| 63 | } |
| 64 | return result; |
| 65 | } |
| 66 | |
| 67 | std::unordered_set<std::string> getAttachedDevices(const ap_xsd::Modules::Module& moduleConfig) { |
| 68 | std::unordered_set<std::string> attachedDeviceSet; |
| 69 | if (moduleConfig.hasAttachedDevices()) { |
| 70 | for (const ap_xsd::AttachedDevices& attachedDevices : moduleConfig.getAttachedDevices()) { |
| 71 | if (attachedDevices.hasItem()) { |
| 72 | attachedDeviceSet.insert(attachedDevices.getItem().begin(), |
| 73 | attachedDevices.getItem().end()); |
| 74 | } |
| 75 | } |
| 76 | } |
| 77 | return attachedDeviceSet; |
| 78 | } |
| 79 | |
| 80 | ConversionResult<AudioDeviceDescription> convertDeviceTypeToAidl(const std::string& xType) { |
| 81 | audio_devices_t legacyDeviceType = AUDIO_DEVICE_NONE; |
| 82 | ::android::DeviceConverter::fromString(xType, legacyDeviceType); |
| 83 | ConversionResult<AudioDeviceDescription> result = |
| 84 | legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyDeviceType); |
| 85 | if ((legacyDeviceType == AUDIO_DEVICE_NONE) || !result.ok()) { |
| 86 | LOG(ERROR) << __func__ << " Review Audio Policy config: " << xType |
| 87 | << " is not a valid device type."; |
| 88 | return unexpected(BAD_VALUE); |
| 89 | } |
| 90 | return result; |
| 91 | } |
| 92 | |
| 93 | ConversionResult<AudioDevice> createAudioDevice( |
| 94 | const ap_xsd::DevicePorts::DevicePort& xDevicePort) { |
| 95 | AudioDevice device = { |
| 96 | .type = VALUE_OR_FATAL(convertDeviceTypeToAidl(xDevicePort.getType())), |
| 97 | .address = xDevicePort.hasAddress() |
| 98 | ? AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>( |
| 99 | xDevicePort.getAddress()) |
| 100 | : AudioDeviceAddress{}}; |
| 101 | if (device.type.type == AudioDeviceType::IN_MICROPHONE && device.type.connection.empty()) { |
| 102 | device.address = "bottom"; |
| 103 | } else if (device.type.type == AudioDeviceType::IN_MICROPHONE_BACK && |
| 104 | device.type.connection.empty()) { |
| 105 | device.address = "back"; |
| 106 | } |
| 107 | return device; |
| 108 | } |
| 109 | |
| 110 | ConversionResult<AudioPortExt> createAudioPortExt( |
| 111 | const ap_xsd::DevicePorts::DevicePort& xDevicePort, |
| 112 | const std::string& xDefaultOutputDevice) { |
| 113 | AudioPortDeviceExt deviceExt = { |
| 114 | .device = VALUE_OR_FATAL(createAudioDevice(xDevicePort)), |
| 115 | .flags = (xDevicePort.getTagName() == xDefaultOutputDevice) |
| 116 | ? 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE |
| 117 | : 0, |
| 118 | .encodedFormats = |
| 119 | xDevicePort.hasEncodedFormats() |
| 120 | ? VALUE_OR_FATAL( |
| 121 | (convertCollectionToAidl<std::string, AudioFormatDescription>( |
| 122 | xDevicePort.getEncodedFormats(), |
| 123 | &convertAudioFormatToAidl))) |
| 124 | : std::vector<AudioFormatDescription>{}, |
| 125 | }; |
| 126 | return AudioPortExt::make<AudioPortExt::Tag::device>(deviceExt); |
| 127 | } |
| 128 | |
| 129 | ConversionResult<AudioPortExt> createAudioPortExt(const ap_xsd::MixPorts::MixPort& xMixPort) { |
| 130 | AudioPortMixExt mixExt = { |
| 131 | .maxOpenStreamCount = |
| 132 | xMixPort.hasMaxOpenCount() ? static_cast<int>(xMixPort.getMaxOpenCount()) : 0, |
| 133 | .maxActiveStreamCount = xMixPort.hasMaxActiveCount() |
| 134 | ? static_cast<int>(xMixPort.getMaxActiveCount()) |
| 135 | : 1, |
| 136 | .recommendedMuteDurationMs = |
| 137 | xMixPort.hasRecommendedMuteDurationMs() |
| 138 | ? static_cast<int>(xMixPort.getRecommendedMuteDurationMs()) |
| 139 | : 0}; |
| 140 | return AudioPortExt::make<AudioPortExt::Tag::mix>(mixExt); |
| 141 | } |
| 142 | |
| 143 | ConversionResult<int> convertGainModeToAidl(const std::vector<ap_xsd::AudioGainMode>& gainModeVec) { |
| 144 | static const char gainModeSeparator = ' '; |
| 145 | int gainModeMask = 0; |
| 146 | for (const ap_xsd::AudioGainMode& gainMode : gainModeVec) { |
| 147 | gainModeMask |= static_cast<int>(::android::GainModeConverter::maskFromString( |
| 148 | ap_xsd::toString(gainMode), &gainModeSeparator)); |
| 149 | } |
| 150 | return gainModeMask; |
| 151 | } |
| 152 | |
| 153 | ConversionResult<AudioChannelLayout> convertChannelMaskToAidl( |
| 154 | const ap_xsd::AudioChannelMask& xChannelMask) { |
| 155 | std::string xChannelMaskLiteral = ap_xsd::toString(xChannelMask); |
| 156 | audio_channel_mask_t legacyChannelMask = ::android::channelMaskFromString(xChannelMaskLiteral); |
| 157 | ConversionResult<AudioChannelLayout> result = |
| 158 | legacy2aidl_audio_channel_mask_t_AudioChannelLayout( |
| 159 | legacyChannelMask, |
| 160 | /* isInput= */ xChannelMaskLiteral.find("AUDIO_CHANNEL_IN_") == 0); |
| 161 | if ((legacyChannelMask == AUDIO_CHANNEL_INVALID) || !result.ok()) { |
| 162 | LOG(ERROR) << __func__ << " Review Audio Policy config: " << xChannelMaskLiteral |
| 163 | << " is not a valid audio channel mask."; |
| 164 | return unexpected(BAD_VALUE); |
| 165 | } |
| 166 | return result; |
| 167 | } |
| 168 | |
| 169 | ConversionResult<AudioGain> convertGainToAidl(const ap_xsd::Gains::Gain& xGain) { |
| 170 | return AudioGain{ |
| 171 | .mode = VALUE_OR_FATAL(convertGainModeToAidl(xGain.getMode())), |
| 172 | .channelMask = |
| 173 | xGain.hasChannel_mask() |
| 174 | ? VALUE_OR_FATAL(convertChannelMaskToAidl(xGain.getChannel_mask())) |
| 175 | : AudioChannelLayout{}, |
| 176 | .minValue = xGain.hasMinValueMB() ? xGain.getMinValueMB() : 0, |
| 177 | .maxValue = xGain.hasMaxValueMB() ? xGain.getMaxValueMB() : 0, |
| 178 | .defaultValue = xGain.hasDefaultValueMB() ? xGain.getDefaultValueMB() : 0, |
| 179 | .stepValue = xGain.hasStepValueMB() ? xGain.getStepValueMB() : 0, |
| 180 | .minRampMs = xGain.hasMinRampMs() ? xGain.getMinRampMs() : 0, |
| 181 | .maxRampMs = xGain.hasMaxRampMs() ? xGain.getMaxRampMs() : 0, |
| 182 | .useForVolume = xGain.hasUseForVolume() ? xGain.getUseForVolume() : false, |
| 183 | }; |
| 184 | } |
| 185 | |
| 186 | ConversionResult<AudioProfile> convertAudioProfileToAidl(const ap_xsd::Profile& xProfile) { |
| 187 | return AudioProfile{ |
| 188 | .format = xProfile.hasFormat() |
| 189 | ? VALUE_OR_FATAL(convertAudioFormatToAidl(xProfile.getFormat())) |
| 190 | : AudioFormatDescription{}, |
| 191 | .channelMasks = |
| 192 | xProfile.hasChannelMasks() |
| 193 | ? VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::AudioChannelMask, |
| 194 | AudioChannelLayout>( |
| 195 | xProfile.getChannelMasks(), &convertChannelMaskToAidl))) |
| 196 | : std::vector<AudioChannelLayout>{}, |
| 197 | .sampleRates = xProfile.hasSamplingRates() |
| 198 | ? VALUE_OR_FATAL((convertCollectionToAidl<int64_t, int>( |
| 199 | xProfile.getSamplingRates(), |
| 200 | [](const int64_t x) -> int { return x; }))) |
| 201 | : std::vector<int>{}}; |
| 202 | } |
| 203 | |
| 204 | ConversionResult<AudioIoFlags> convertIoFlagsToAidl( |
| 205 | const std::vector<ap_xsd::AudioInOutFlag>& flags, const ap_xsd::Role role, |
| 206 | bool flagsForMixPort) { |
| 207 | static const char flagSeparator = ' '; |
| 208 | int flagMask = 0; |
| 209 | if ((role == ap_xsd::Role::sink && flagsForMixPort) || |
| 210 | (role == ap_xsd::Role::source && !flagsForMixPort)) { |
| 211 | for (const ap_xsd::AudioInOutFlag& flag : flags) { |
| 212 | flagMask |= static_cast<int>(::android::InputFlagConverter::maskFromString( |
| 213 | ap_xsd::toString(flag), &flagSeparator)); |
| 214 | } |
| 215 | return AudioIoFlags::make<AudioIoFlags::Tag::input>(flagMask); |
| 216 | } else { |
| 217 | for (const ap_xsd::AudioInOutFlag& flag : flags) { |
| 218 | flagMask |= static_cast<int>(::android::OutputFlagConverter::maskFromString( |
| 219 | ap_xsd::toString(flag), &flagSeparator)); |
| 220 | } |
| 221 | } |
| 222 | return AudioIoFlags::make<AudioIoFlags::Tag::output>(flagMask); |
| 223 | } |
| 224 | |
| 225 | ConversionResult<AudioPort> convertDevicePortToAidl( |
| 226 | const ap_xsd::DevicePorts::DevicePort& xDevicePort, const std::string& xDefaultOutputDevice, |
| 227 | int32_t& nextPortId) { |
| 228 | return AudioPort{ |
| 229 | .id = nextPortId++, |
| 230 | .name = NON_EMPTY_STRING_OR_FATAL(xDevicePort.getTagName()), |
| 231 | .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>( |
| 232 | xDevicePort.getProfile(), convertAudioProfileToAidl))), |
| 233 | .flags = VALUE_OR_FATAL(convertIoFlagsToAidl({}, xDevicePort.getRole(), false)), |
| 234 | .gains = VALUE_OR_FATAL( |
| 235 | (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>( |
| 236 | xDevicePort.getGains(), &ap_xsd::Gains::getGain, convertGainToAidl))), |
| 237 | |
| 238 | .ext = VALUE_OR_FATAL(createAudioPortExt(xDevicePort, xDefaultOutputDevice))}; |
| 239 | } |
| 240 | |
| 241 | ConversionResult<std::vector<AudioPort>> convertDevicePortsInModuleToAidl( |
| 242 | const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) { |
| 243 | std::vector<AudioPort> audioPortVec; |
| 244 | std::vector<ap_xsd::DevicePorts> xDevicePortsVec = xModuleConfig.getDevicePorts(); |
| 245 | if (xDevicePortsVec.size() > 1) { |
| 246 | LOG(ERROR) << __func__ << "Having multiple '<devicePorts>' elements is not allowed, found: " |
| 247 | << xDevicePortsVec.size(); |
| 248 | return unexpected(BAD_VALUE); |
| 249 | } |
| 250 | if (!xDevicePortsVec.empty()) { |
| 251 | const std::string xDefaultOutputDevice = xModuleConfig.hasDefaultOutputDevice() |
| 252 | ? xModuleConfig.getDefaultOutputDevice() |
| 253 | : ""; |
| 254 | audioPortVec.reserve(xDevicePortsVec[0].getDevicePort().size()); |
| 255 | for (const ap_xsd::DevicePorts& xDevicePortsType : xDevicePortsVec) { |
| 256 | for (const ap_xsd::DevicePorts::DevicePort& xDevicePort : |
| 257 | xDevicePortsType.getDevicePort()) { |
| 258 | audioPortVec.push_back(VALUE_OR_FATAL( |
| 259 | convertDevicePortToAidl(xDevicePort, xDefaultOutputDevice, nextPortId))); |
| 260 | } |
| 261 | } |
| 262 | } |
| 263 | const std::unordered_set<std::string> xAttachedDeviceSet = getAttachedDevices(xModuleConfig); |
| 264 | for (const auto& port : audioPortVec) { |
| 265 | const auto& devicePort = port.ext.get<AudioPortExt::device>(); |
| 266 | if (xAttachedDeviceSet.count(port.name) != devicePort.device.type.connection.empty()) { |
| 267 | LOG(ERROR) << __func__ << ": Review Audio Policy config: <attachedDevices> " |
| 268 | << "list is incorrect or devicePort \"" << port.name |
| 269 | << "\" type= " << devicePort.device.type.toString() << " is incorrect."; |
| 270 | return unexpected(BAD_VALUE); |
| 271 | } |
| 272 | } |
| 273 | return audioPortVec; |
| 274 | } |
| 275 | |
| 276 | ConversionResult<AudioPort> convertMixPortToAidl(const ap_xsd::MixPorts::MixPort& xMixPort, |
| 277 | int32_t& nextPortId) { |
| 278 | return AudioPort{ |
| 279 | .id = nextPortId++, |
| 280 | .name = NON_EMPTY_STRING_OR_FATAL(xMixPort.getName()), |
| 281 | .profiles = VALUE_OR_FATAL((convertCollectionToAidl<ap_xsd::Profile, AudioProfile>( |
| 282 | xMixPort.getProfile(), convertAudioProfileToAidl))), |
| 283 | .flags = xMixPort.hasFlags() |
| 284 | ? VALUE_OR_FATAL(convertIoFlagsToAidl(xMixPort.getFlags(), |
| 285 | xMixPort.getRole(), true)) |
| 286 | : VALUE_OR_FATAL(convertIoFlagsToAidl({}, xMixPort.getRole(), true)), |
| 287 | .gains = VALUE_OR_FATAL( |
| 288 | (convertWrappedCollectionToAidl<ap_xsd::Gains, ap_xsd::Gains::Gain, AudioGain>( |
| 289 | xMixPort.getGains(), &ap_xsd::Gains::getGain, &convertGainToAidl))), |
| 290 | .ext = VALUE_OR_FATAL(createAudioPortExt(xMixPort)), |
| 291 | }; |
| 292 | } |
| 293 | |
| 294 | ConversionResult<std::vector<AudioPort>> convertMixPortsInModuleToAidl( |
| 295 | const ap_xsd::Modules::Module& xModuleConfig, int32_t& nextPortId) { |
| 296 | std::vector<AudioPort> audioPortVec; |
| 297 | std::vector<ap_xsd::MixPorts> xMixPortsVec = xModuleConfig.getMixPorts(); |
| 298 | if (xMixPortsVec.size() > 1) { |
| 299 | LOG(ERROR) << __func__ << "Having multiple '<mixPorts>' elements is not allowed, found: " |
| 300 | << xMixPortsVec.size(); |
| 301 | return unexpected(BAD_VALUE); |
| 302 | } |
| 303 | if (!xMixPortsVec.empty()) { |
| 304 | audioPortVec.reserve(xMixPortsVec[0].getMixPort().size()); |
| 305 | for (const ap_xsd::MixPorts& xMixPortsType : xMixPortsVec) { |
| 306 | for (const ap_xsd::MixPorts::MixPort& xMixPort : xMixPortsType.getMixPort()) { |
| 307 | audioPortVec.push_back(VALUE_OR_FATAL(convertMixPortToAidl(xMixPort, nextPortId))); |
| 308 | } |
| 309 | } |
| 310 | } |
| 311 | return audioPortVec; |
| 312 | } |
| 313 | |
| 314 | ConversionResult<int32_t> getSinkPortId(const ap_xsd::Routes::Route& xRoute, |
| 315 | const std::unordered_map<std::string, int32_t>& portMap) { |
| 316 | auto portMapIter = portMap.find(xRoute.getSink()); |
| 317 | if (portMapIter == portMap.end()) { |
| 318 | LOG(ERROR) << __func__ << " Review Audio Policy config: audio route" |
| 319 | << "has sink: " << xRoute.getSink() |
| 320 | << " which is neither a device port nor mix port."; |
| 321 | return unexpected(BAD_VALUE); |
| 322 | } |
| 323 | return portMapIter->second; |
| 324 | } |
| 325 | |
| 326 | ConversionResult<std::vector<int32_t>> getSourcePortIds( |
| 327 | const ap_xsd::Routes::Route& xRoute, |
| 328 | const std::unordered_map<std::string, int32_t>& portMap) { |
| 329 | std::vector<int32_t> sourcePortIds; |
| 330 | for (const std::string& rawSource : ::android::base::Split(xRoute.getSources(), ",")) { |
| 331 | const std::string source = ::android::base::Trim(rawSource); |
| 332 | auto portMapIter = portMap.find(source); |
| 333 | if (portMapIter == portMap.end()) { |
| 334 | LOG(ERROR) << __func__ << " Review Audio Policy config: audio route" |
| 335 | << "has source \"" << source |
| 336 | << "\" which is neither a device port nor mix port."; |
| 337 | return unexpected(BAD_VALUE); |
| 338 | } |
| 339 | sourcePortIds.push_back(portMapIter->second); |
| 340 | } |
| 341 | return sourcePortIds; |
| 342 | } |
| 343 | |
| 344 | ConversionResult<AudioRoute> convertRouteToAidl(const ap_xsd::Routes::Route& xRoute, |
| 345 | const std::vector<AudioPort>& aidlAudioPorts) { |
| 346 | std::unordered_map<std::string, int32_t> portMap; |
| 347 | for (const AudioPort& port : aidlAudioPorts) { |
| 348 | portMap.insert({port.name, port.id}); |
| 349 | } |
| 350 | return AudioRoute{.sourcePortIds = VALUE_OR_FATAL(getSourcePortIds(xRoute, portMap)), |
| 351 | .sinkPortId = VALUE_OR_FATAL(getSinkPortId(xRoute, portMap)), |
| 352 | .isExclusive = (xRoute.getType() == ap_xsd::MixType::mux)}; |
| 353 | } |
| 354 | |
| 355 | ConversionResult<std::vector<AudioRoute>> convertRoutesInModuleToAidl( |
| 356 | const ap_xsd::Modules::Module& xModuleConfig, |
| 357 | const std::vector<AudioPort>& aidlAudioPorts) { |
| 358 | std::vector<AudioRoute> audioRouteVec; |
| 359 | std::vector<ap_xsd::Routes> xRoutesVec = xModuleConfig.getRoutes(); |
| 360 | if (!xRoutesVec.empty()) { |
| 361 | /* |
| 362 | * xRoutesVec likely only contains one element; that is, it's |
| 363 | * likely that all ap_xsd::Routes::MixPort types that we need to convert |
| 364 | * are inside of xRoutesVec[0]. |
| 365 | */ |
| 366 | audioRouteVec.reserve(xRoutesVec[0].getRoute().size()); |
| 367 | for (const ap_xsd::Routes& xRoutesType : xRoutesVec) { |
| 368 | for (const ap_xsd::Routes::Route& xRoute : xRoutesType.getRoute()) { |
| 369 | audioRouteVec.push_back(VALUE_OR_FATAL(convertRouteToAidl(xRoute, aidlAudioPorts))); |
| 370 | } |
| 371 | } |
| 372 | } |
| 373 | return audioRouteVec; |
| 374 | } |
| 375 | |
| 376 | ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl( |
| 377 | const ap_xsd::Modules::Module& xModuleConfig) { |
| 378 | auto result = std::make_unique<Module::Configuration>(); |
| 379 | auto& aidlModuleConfig = *result; |
| 380 | std::vector<AudioPort> devicePorts = VALUE_OR_FATAL( |
| 381 | convertDevicePortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId)); |
| 382 | |
| 383 | // The XML config does not specify the default input device. |
| 384 | // Assign the first attached input device as the default. |
| 385 | for (auto& port : devicePorts) { |
| 386 | if (port.flags.getTag() != AudioIoFlags::input) continue; |
| 387 | auto& deviceExt = port.ext.get<AudioPortExt::device>(); |
| 388 | if (!deviceExt.device.type.connection.empty()) continue; |
| 389 | deviceExt.flags |= 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE; |
| 390 | break; |
| 391 | } |
| 392 | |
| 393 | std::vector<AudioPort> mixPorts = VALUE_OR_FATAL( |
| 394 | convertMixPortsInModuleToAidl(xModuleConfig, aidlModuleConfig.nextPortId)); |
| 395 | aidlModuleConfig.ports.reserve(devicePorts.size() + mixPorts.size()); |
| 396 | aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), devicePorts.begin(), |
| 397 | devicePorts.end()); |
| 398 | aidlModuleConfig.ports.insert(aidlModuleConfig.ports.end(), mixPorts.begin(), mixPorts.end()); |
| 399 | |
| 400 | aidlModuleConfig.routes = |
| 401 | VALUE_OR_FATAL(convertRoutesInModuleToAidl(xModuleConfig, aidlModuleConfig.ports)); |
| 402 | return result; |
| 403 | } |
| 404 | |
| 405 | ConversionResult<AudioHalCapCriterion> convertCapCriterionToAidl( |
| 406 | const eng_xsd::CriterionType& xsdcCriterion) { |
| 407 | AudioHalCapCriterion aidlCapCriterion; |
| 408 | aidlCapCriterion.name = xsdcCriterion.getName(); |
| 409 | aidlCapCriterion.criterionTypeName = xsdcCriterion.getType(); |
| 410 | aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default(); |
| 411 | return aidlCapCriterion; |
| 412 | } |
| 413 | |
| 414 | ConversionResult<std::string> convertCriterionTypeValueToAidl( |
| 415 | const eng_xsd::ValueType& xsdcCriterionTypeValue) { |
| 416 | return xsdcCriterionTypeValue.getLiteral(); |
| 417 | } |
| 418 | |
| 419 | ConversionResult<AudioHalCapCriterionType> convertCapCriterionTypeToAidl( |
| 420 | const eng_xsd::CriterionTypeType& xsdcCriterionType) { |
| 421 | AudioHalCapCriterionType aidlCapCriterionType; |
| 422 | aidlCapCriterionType.name = xsdcCriterionType.getName(); |
| 423 | aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType())); |
| 424 | aidlCapCriterionType.values = VALUE_OR_RETURN( |
| 425 | (convertWrappedCollectionToAidl<eng_xsd::ValuesType, eng_xsd::ValueType, std::string>( |
| 426 | xsdcCriterionType.getValues(), &eng_xsd::ValuesType::getValue, |
| 427 | &convertCriterionTypeValueToAidl))); |
| 428 | return aidlCapCriterionType; |
| 429 | } |
| 430 | |
| 431 | ConversionResult<AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl( |
| 432 | const std::string& xsdcCurvePoint) { |
| 433 | AudioHalVolumeCurve::CurvePoint aidlCurvePoint{}; |
| 434 | if ((sscanf(xsdcCurvePoint.c_str(), "%" SCNd8 ",%d", &aidlCurvePoint.index, |
| 435 | &aidlCurvePoint.attenuationMb) != 2) || |
| 436 | (aidlCurvePoint.index < AudioHalVolumeCurve::CurvePoint::MIN_INDEX) || |
| 437 | (aidlCurvePoint.index > AudioHalVolumeCurve::CurvePoint::MAX_INDEX)) { |
| 438 | LOG(ERROR) << __func__ << " Review Audio Policy config: volume curve point:" |
| 439 | << "\"" << xsdcCurvePoint << "\" is invalid"; |
| 440 | return unexpected(BAD_VALUE); |
| 441 | } |
| 442 | return aidlCurvePoint; |
| 443 | } |
| 444 | } // namespace aidl::android::hardware::audio::core::internal |