diff --git a/audio/aidl/common/Android.bp b/audio/aidl/common/Android.bp index 5c0c685bdf..c14d19dd7f 100644 --- a/audio/aidl/common/Android.bp +++ b/audio/aidl/common/Android.bp @@ -32,10 +32,12 @@ cc_library { header_libs: [ "libbase_headers", "libsystem_headers", + "libutils_headers", ], export_header_lib_headers: [ "libbase_headers", "libsystem_headers", + "libutils_headers", ], srcs: [ "StreamWorker.cpp", diff --git a/audio/aidl/common/include/Utils.h b/audio/aidl/common/include/Utils.h index dd216e59ef..dd0c7e7393 100644 --- a/audio/aidl/common/include/Utils.h +++ b/audio/aidl/common/include/Utils.h @@ -29,8 +29,10 @@ #include #include #include +#include #include #include +#include namespace ndk { @@ -58,6 +60,36 @@ constexpr std::array<::aidl::android::media::audio::common::AudioMode, 5> kValid ::aidl::android::media::audio::common::AudioMode::CALL_SCREEN, }; +constexpr std::array<::aidl::android::media::audio::common::AudioPolicyForcedConfig, 17> + kValidAudioPolicyForcedConfig = { + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::NONE, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::SPEAKER, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::HEADPHONES, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_SCO, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_A2DP, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::WIRED_ACCESSORY, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_CAR_DOCK, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_DESK_DOCK, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::ANALOG_DOCK, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::DIGITAL_DOCK, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::NO_BT_A2DP, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::SYSTEM_ENFORCED, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig:: + HDMI_SYSTEM_AUDIO_ENFORCED, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig:: + ENCODED_SURROUND_NEVER, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig:: + ENCODED_SURROUND_ALWAYS, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig:: + ENCODED_SURROUND_MANUAL, + ::aidl::android::media::audio::common::AudioPolicyForcedConfig::BT_BLE, +}; + +constexpr bool iequals(const std::string& str1, const std::string& str2) { + return str1.length() == str2.length() && + !fasticmp(str1.c_str(), str2.c_str(), str1.length()); +} + constexpr size_t getPcmSampleSizeInBytes(::aidl::android::media::audio::common::PcmType pcm) { using ::aidl::android::media::audio::common::PcmType; switch (pcm) { @@ -133,6 +165,12 @@ constexpr bool isValidAudioMode(::aidl::android::media::audio::common::AudioMode kValidAudioModes.end(); } +constexpr bool isValidAudioPolicyForcedConfig( + ::aidl::android::media::audio::common::AudioPolicyForcedConfig config) { + return std::find(kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(), + config) != kValidAudioPolicyForcedConfig.end(); +} + static inline bool maybeVendorExtension(const std::string& s) { // Only checks whether the string starts with the "vendor prefix". static const std::string vendorPrefix = "VX_"; diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index f5b590bc36..f51f65e60e 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -54,6 +54,7 @@ cc_library { "AidlConversionXsdc.cpp", "AudioPolicyConfigXmlConverter.cpp", "Bluetooth.cpp", + "CapEngineConfigXmlConverter.cpp", "Config.cpp", "Configuration.cpp", "EngineConfigXmlConverter.cpp", @@ -83,14 +84,17 @@ cc_library { "usb/UsbAlsaMixerControl.cpp", ], generated_sources: [ + "audio_policy_capengine_configuration_aidl_default", "audio_policy_configuration_aidl_default", "audio_policy_engine_configuration_aidl_default", ], generated_headers: [ + "audio_policy_capengine_configuration_aidl_default", "audio_policy_configuration_aidl_default", "audio_policy_engine_configuration_aidl_default", ], export_generated_headers: [ + "audio_policy_capengine_configuration_aidl_default", "audio_policy_configuration_aidl_default", "audio_policy_engine_configuration_aidl_default", ], diff --git a/audio/aidl/default/CapEngineConfigXmlConverter.cpp b/audio/aidl/default/CapEngineConfigXmlConverter.cpp new file mode 100644 index 0000000000..821066415f --- /dev/null +++ b/audio/aidl/default/CapEngineConfigXmlConverter.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "AHAL_Config" + +#include +#include +#include +#include +#include +#include + +#include "core-impl/CapEngineConfigXmlConverter.h" +#include "core-impl/XsdcConversion.h" + +using aidl::android::hardware::audio::common::iequals; +using aidl::android::media::audio::common::AudioDeviceAddress; +using aidl::android::media::audio::common::AudioDeviceDescription; +using aidl::android::media::audio::common::AudioHalCapConfiguration; +using aidl::android::media::audio::common::AudioHalCapCriterionV2; +using aidl::android::media::audio::common::AudioHalCapDomain; +using aidl::android::media::audio::common::AudioHalCapParameter; +using aidl::android::media::audio::common::AudioHalCapRule; +using aidl::android::media::audio::common::AudioPolicyForceUse; +using aidl::android::media::audio::common::AudioSource; +using aidl::android::media::audio::common::AudioStreamType; + +using ::android::BAD_VALUE; +using ::android::base::unexpected; +using ::android::utilities::convertTo; + +namespace eng_xsd = android::audio::policy::capengine::configuration; + +namespace aidl::android::hardware::audio::core::internal { + +static constexpr const char* gStrategiesParameter = "product_strategies"; +static constexpr const char* gInputSourcesParameter = "input_sources"; +static constexpr const char* gStreamsParameter = "streams"; +static constexpr const char* gOutputDevicesParameter = "selected_output_devices"; +static constexpr const char* gOutputDeviceAddressParameter = "device_address"; +static constexpr const char* gStrategyPrefix = "vx_"; +static constexpr const char* gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_"; +static constexpr const char* gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_"; +static constexpr const char* gLegacyStreamPrefix = "AUDIO_STREAM_"; +static constexpr const char* gLegacySourcePrefix = "AUDIO_SOURCE_"; + +std::optional>>& +CapEngineConfigXmlConverter::getAidlCapEngineConfig() { + return mAidlCapDomains; +} + +ConversionResult convertCriterionRuleToAidl( + const eng_xsd::SelectionCriterionRuleType& xsdcRule) { + using Tag = AudioHalCapCriterionV2::Tag; + AudioHalCapRule::CriterionRule rule{}; + std::string criterionName = xsdcRule.getSelectionCriterion(); + std::string criterionValue = xsdcRule.getValue(); + if (iequals(criterionName, toString(Tag::availableInputDevices))) { + rule.criterion = AudioHalCapCriterionV2::make(); + rule.criterionTypeValue = + VALUE_OR_RETURN(convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue)); + } else if (iequals(criterionName, toString(Tag::availableOutputDevices))) { + rule.criterion = AudioHalCapCriterionV2::make(); + rule.criterionTypeValue = VALUE_OR_RETURN( + convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue)); + } else if (iequals(criterionName, toString(Tag::availableInputDevicesAddresses))) { + rule.criterion = AudioHalCapCriterionV2::make(); + rule.criterionTypeValue = + AudioDeviceAddress::make(criterionValue); + } else if (iequals(criterionName, toString(Tag::availableOutputDevicesAddresses))) { + rule.criterion = AudioHalCapCriterionV2::make(); + rule.criterionTypeValue = + AudioDeviceAddress::make(criterionValue); + } else if (iequals(criterionName, toString(Tag::telephonyMode))) { + rule.criterion = AudioHalCapCriterionV2::make(); + rule.criterionTypeValue = VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue)); + } else if (!fastcmp(criterionName.c_str(), kXsdcForceConfigForUse, + strlen(kXsdcForceConfigForUse))) { + rule.criterion = AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertForceUseCriterionToAidl(criterionName))); + rule.criterionTypeValue = VALUE_OR_RETURN(convertForcedConfigToAidl(criterionValue)); + } else { + LOG(ERROR) << __func__ << " unrecognized criterion " << criterionName; + return unexpected(BAD_VALUE); + } + if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Excludes) { + rule.matchingRule = AudioHalCapRule::MatchingRule::EXCLUDES; + } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Includes) { + rule.matchingRule = AudioHalCapRule::MatchingRule::INCLUDES; + } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::Is) { + rule.matchingRule = AudioHalCapRule::MatchingRule::IS; + } else if (xsdcRule.getMatchesWhen() == eng_xsd::MatchesWhenEnum::IsNot) { + rule.matchingRule = AudioHalCapRule::MatchingRule::IS_NOT; + } else { + LOG(ERROR) << "Unsupported match when rule."; + return unexpected(BAD_VALUE); + } + return rule; +} + +ConversionResult convertRule(const eng_xsd::CompoundRuleType& xsdcCompoundRule) { + AudioHalCapRule rule{}; + bool isPreviousCompoundRule = true; + if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::Any) { + rule.compoundRule = AudioHalCapRule::CompoundRule::ANY; + } else if (xsdcCompoundRule.getType() == eng_xsd::TypeEnum::All) { + rule.compoundRule = AudioHalCapRule::CompoundRule::ALL; + } else { + LOG(ERROR) << "Unsupported compound rule type."; + return unexpected(BAD_VALUE); + } + for (const auto& childXsdcCoumpoundRule : xsdcCompoundRule.getCompoundRule_optional()) { + if (childXsdcCoumpoundRule.hasCompoundRule_optional()) { + rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule))); + } else if (childXsdcCoumpoundRule.hasSelectionCriterionRule_optional()) { + rule.nestedRules.push_back(VALUE_OR_FATAL(convertRule(childXsdcCoumpoundRule))); + } + } + if (xsdcCompoundRule.hasSelectionCriterionRule_optional()) { + for (const auto& xsdcRule : xsdcCompoundRule.getSelectionCriterionRule_optional()) { + rule.criterionRules.push_back(VALUE_OR_FATAL(convertCriterionRuleToAidl(xsdcRule))); + } + } + return rule; +} + +ConversionResult getAudioProductStrategyId(const std::string& path) { + std::vector strings; + std::istringstream pathStream(path); + std::string stringToken; + while (getline(pathStream, stringToken, '/')) { + std::size_t pos = stringToken.find(gStrategyPrefix); + if (pos != std::string::npos) { + std::string strategyIdLiteral = stringToken.substr(pos + std::strlen(gStrategyPrefix)); + int strategyId; + if (!convertTo(strategyIdLiteral, strategyId)) { + LOG(ERROR) << "Invalid strategy " << stringToken << " from path " << path; + return unexpected(BAD_VALUE); + } + return strategyId; + } + } + return unexpected(BAD_VALUE); +} + +ConversionResult getAudioSource(const std::string& path) { + std::vector strings; + std::istringstream pathStream(path); + std::string stringToken; + while (getline(pathStream, stringToken, '/')) { + if (stringToken.find(gInputSourcesParameter) != std::string::npos) { + getline(pathStream, stringToken, '/'); + std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(), + [](char c) { return std::toupper(c); }); + std::string legacySourceLiteral = "AUDIO_SOURCE_" + stringToken; + audio_source_t legacySource; + if (!::android::SourceTypeConverter::fromString(legacySourceLiteral, legacySource)) { + LOG(ERROR) << "Invalid source " << stringToken << " from path " << path; + return unexpected(BAD_VALUE); + } + return legacy2aidl_audio_source_t_AudioSource(legacySource); + } + } + return unexpected(BAD_VALUE); +} + +ConversionResult getAudioStreamType(const std::string& path) { + std::vector strings; + std::istringstream pathStream(path); + std::string stringToken; + + while (getline(pathStream, stringToken, '/')) { + if (stringToken.find(gStreamsParameter) != std::string::npos) { + getline(pathStream, stringToken, '/'); + std::transform(stringToken.begin(), stringToken.end(), stringToken.begin(), + [](char c) { return std::toupper(c); }); + std::string legacyStreamLiteral = std::string(gLegacyStreamPrefix) + stringToken; + audio_stream_type_t legacyStream; + if (!::android::StreamTypeConverter::fromString(legacyStreamLiteral, legacyStream)) { + LOG(ERROR) << "Invalid stream " << stringToken << " from path " << path; + return unexpected(BAD_VALUE); + } + return legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStream); + } + } + return unexpected(BAD_VALUE); +} + +ConversionResult toUpperAndAppendPrefix(const std::string& capName, + const std::string& legacyPrefix) { + std::string legacyName = capName; + std::transform(legacyName.begin(), legacyName.end(), legacyName.begin(), + [](char c) { return std::toupper(c); }); + return legacyPrefix + legacyName; +} + +ConversionResult CapEngineConfigXmlConverter::convertParamToAidl( + const eng_xsd::ConfigurableElementSettingsType& element) { + const auto& path = element.getPath(); + + AudioHalCapParameter parameterSetting; + if (path.find(gStrategiesParameter) != std::string::npos) { + int strategyId = VALUE_OR_FATAL(getAudioProductStrategyId(path)); + if (path.find(gOutputDevicesParameter) != std::string::npos) { + // Value is 1 or 0 + if (!element.hasBitParameter_optional()) { + LOG(ERROR) << "Invalid strategy value type"; + return unexpected(BAD_VALUE); + } + // Convert name to output device type + const auto* xsdcParam = element.getFirstBitParameter_optional(); + std::string outputDevice = VALUE_OR_FATAL(toUpperAndAppendPrefix( + eng_xsd::toString(xsdcParam->getName()), gLegacyOutputDevicePrefix)); + audio_devices_t legacyType; + if (!::android::OutputDeviceConverter::fromString(outputDevice, legacyType)) { + LOG(ERROR) << "Invalid strategy device type " << outputDevice; + return unexpected(BAD_VALUE); + } + AudioDeviceDescription aidlDevice = + VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType)); + bool isSelected; + if (!convertTo(xsdcParam->getValue(), isSelected)) { + LOG(ERROR) << "Invalid strategy device selection value " << xsdcParam->getValue(); + return unexpected(BAD_VALUE); + } + parameterSetting = + AudioHalCapParameter::StrategyDevice(aidlDevice, strategyId, isSelected); + } else if (path.find(gOutputDeviceAddressParameter) != std::string::npos) { + // Value is the address + if (!element.hasStringParameter_optional()) { + return unexpected(BAD_VALUE); + } + std::string address = element.getFirstStringParameter_optional()->getValue(); + parameterSetting = AudioHalCapParameter::StrategyDeviceAddress( + AudioDeviceAddress(address), strategyId); + } + } else if (path.find(gInputSourcesParameter) != std::string::npos) { + // Value is 1 or 0 + if (!element.hasBitParameter_optional()) { + LOG(ERROR) << "Invalid source value type"; + return unexpected(BAD_VALUE); + } + AudioSource audioSourceAidl = VALUE_OR_FATAL(getAudioSource(path)); + const auto* xsdcParam = element.getFirstBitParameter_optional(); + std::string inputDeviceLiteral = VALUE_OR_FATAL(toUpperAndAppendPrefix( + eng_xsd::toString(xsdcParam->getName()), gLegacyInputDevicePrefix)); + audio_devices_t inputDeviceType; + if (!::android::InputDeviceConverter::fromString(inputDeviceLiteral, inputDeviceType)) { + LOG(ERROR) << "Invalid source device type " << inputDeviceLiteral; + return unexpected(BAD_VALUE); + } + AudioDeviceDescription aidlDevice = + VALUE_OR_FATAL(legacy2aidl_audio_devices_t_AudioDeviceDescription(inputDeviceType)); + + bool isSelected; + if (!convertTo(xsdcParam->getValue(), isSelected)) { + LOG(ERROR) << "Invalid source value type " << xsdcParam->getValue(); + return unexpected(BAD_VALUE); + } + parameterSetting = + AudioHalCapParameter::InputSourceDevice(aidlDevice, audioSourceAidl, isSelected); + } else if (path.find(gStreamsParameter) != std::string::npos) { + AudioStreamType audioStreamAidl = VALUE_OR_FATAL(getAudioStreamType(path)); + if (!element.hasEnumParameter_optional()) { + LOG(ERROR) << "Invalid stream value type"; + return unexpected(BAD_VALUE); + } + const auto* xsdcParam = element.getFirstEnumParameter_optional(); + std::string profileLiteral = + VALUE_OR_FATAL(toUpperAndAppendPrefix(xsdcParam->getValue(), gLegacyStreamPrefix)); + audio_stream_type_t profileLegacyStream; + if (!::android::StreamTypeConverter::fromString(profileLiteral, profileLegacyStream)) { + LOG(ERROR) << "Invalid stream value " << profileLiteral; + return unexpected(BAD_VALUE); + } + AudioStreamType profileStreamAidl = VALUE_OR_FATAL( + legacy2aidl_audio_stream_type_t_AudioStreamType(profileLegacyStream)); + parameterSetting = + AudioHalCapParameter::StreamVolumeProfile(audioStreamAidl, profileStreamAidl); + } + return parameterSetting; +} + +ConversionResult> +CapEngineConfigXmlConverter::convertSettingToAidl( + const eng_xsd::SettingsType::Configuration& xsdcSetting) { + std::vector aidlCapParameterSettings; + for (const auto& element : xsdcSetting.getConfigurableElement()) { + aidlCapParameterSettings.push_back(VALUE_OR_FATAL(convertParamToAidl(element))); + } + return aidlCapParameterSettings; +} + +ConversionResult CapEngineConfigXmlConverter::convertConfigurationToAidl( + const eng_xsd::ConfigurationsType::Configuration& xsdcConfiguration, + const eng_xsd::SettingsType::Configuration& xsdcSettingConfiguration) { + AudioHalCapConfiguration aidlCapConfiguration; + aidlCapConfiguration.name = xsdcConfiguration.getName(); + if (xsdcConfiguration.hasCompoundRule()) { + if (xsdcConfiguration.getCompoundRule().size() != 1) { + return unexpected(BAD_VALUE); + } + aidlCapConfiguration.rule = + VALUE_OR_FATAL(convertRule(xsdcConfiguration.getCompoundRule()[0])); + aidlCapConfiguration.parameterSettings = + VALUE_OR_FATAL(convertSettingToAidl(xsdcSettingConfiguration)); + } + return aidlCapConfiguration; +} + +ConversionResult getConfigurationByName( + const std::string& name, const std::vector& xsdcSettingsVec) { + for (const auto& xsdcSettings : xsdcSettingsVec) { + for (const auto& xsdcConfiguration : xsdcSettings.getConfiguration()) { + if (xsdcConfiguration.getName() == name) { + return xsdcConfiguration; + } + } + } + LOG(ERROR) << __func__ << " failed to find configuration " << name; + return unexpected(BAD_VALUE); +} + +ConversionResult> +CapEngineConfigXmlConverter::convertConfigurationsToAidl( + const std::vector& xsdcConfigurationsVec, + const std::vector& xsdcSettingsVec) { + if (xsdcConfigurationsVec.empty() || xsdcSettingsVec.empty()) { + LOG(ERROR) << __func__ << " empty configurations/settings"; + return unexpected(BAD_VALUE); + } + std::vector aidlConfigurations; + for (const auto& xsdcConfigurations : xsdcConfigurationsVec) { + for (const auto& xsdcConfiguration : xsdcConfigurations.getConfiguration()) { + auto xsdcSettingConfiguration = VALUE_OR_FATAL( + getConfigurationByName(xsdcConfiguration.getName(), xsdcSettingsVec)); + aidlConfigurations.push_back(VALUE_OR_FATAL( + convertConfigurationToAidl(xsdcConfiguration, xsdcSettingConfiguration))); + } + } + return aidlConfigurations; +} + +ConversionResult CapEngineConfigXmlConverter::convertConfigurableDomainToAidl( + const eng_xsd::ConfigurableDomainType& xsdcConfigurableDomain) { + AudioHalCapDomain aidlConfigurableDomain; + + aidlConfigurableDomain.name = xsdcConfigurableDomain.getName(); + if (xsdcConfigurableDomain.hasSequenceAware() && xsdcConfigurableDomain.getSequenceAware()) { + LOG(ERROR) << "sequence aware not supported."; + return unexpected(BAD_VALUE); + } + if (xsdcConfigurableDomain.hasConfigurations() && xsdcConfigurableDomain.hasSettings()) { + aidlConfigurableDomain.configurations = VALUE_OR_FATAL(convertConfigurationsToAidl( + xsdcConfigurableDomain.getConfigurations(), xsdcConfigurableDomain.getSettings())); + } + return aidlConfigurableDomain; +} + +void CapEngineConfigXmlConverter::init() { + if (getXsdcConfig()->hasConfigurableDomain()) { + mAidlCapDomains = std::make_optional<>(VALUE_OR_FATAL( + (convertCollectionToAidlOptionalValues( + getXsdcConfig()->getConfigurableDomain(), + std::bind(&CapEngineConfigXmlConverter::convertConfigurableDomainToAidl, + this, std::placeholders::_1))))); + } else { + mAidlCapDomains = std::nullopt; + } +} + +} // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/EngineConfigXmlConverter.cpp b/audio/aidl/default/EngineConfigXmlConverter.cpp index 631cdce1a0..5a8b0a3f03 100644 --- a/audio/aidl/default/EngineConfigXmlConverter.cpp +++ b/audio/aidl/default/EngineConfigXmlConverter.cpp @@ -26,15 +26,19 @@ #include #include +#include "core-impl/CapEngineConfigXmlConverter.h" #include "core-impl/EngineConfigXmlConverter.h" #include "core-impl/XsdcConversion.h" +using aidl::android::hardware::audio::core::internal::CapEngineConfigXmlConverter; +using aidl::android::hardware::audio::core::internal::convertAudioUsageToAidl; using aidl::android::media::audio::common::AudioAttributes; using aidl::android::media::audio::common::AudioContentType; using aidl::android::media::audio::common::AudioFlag; using aidl::android::media::audio::common::AudioHalAttributesGroup; using aidl::android::media::audio::common::AudioHalCapCriterion; using aidl::android::media::audio::common::AudioHalCapCriterionType; +using aidl::android::media::audio::common::AudioHalCapCriterionV2; using aidl::android::media::audio::common::AudioHalEngineConfig; using aidl::android::media::audio::common::AudioHalProductStrategy; using aidl::android::media::audio::common::AudioHalVolumeCurve; @@ -43,6 +47,7 @@ using aidl::android::media::audio::common::AudioProductStrategyType; using aidl::android::media::audio::common::AudioSource; using aidl::android::media::audio::common::AudioStreamType; using aidl::android::media::audio::common::AudioUsage; + using ::android::BAD_VALUE; using ::android::base::unexpected; @@ -50,6 +55,10 @@ namespace eng_xsd = android::audio::policy::engine::configuration; namespace aidl::android::hardware::audio::core::internal { +/** Default path of audio policy cap engine configuration file. */ +static constexpr char kCapEngineConfigFileName[] = + "/parameter-framework/Settings/Policy/PolicyConfigurableDomains.xml"; + void EngineConfigXmlConverter::initProductStrategyMap() { #define STRATEGY_ENTRY(name) {"STRATEGY_" #name, static_cast(AudioProductStrategyType::name)} @@ -74,6 +83,13 @@ ConversionResult EngineConfigXmlConverter::convertProductStrategyNameToAidl return it->second; } +ConversionResult EngineConfigXmlConverter::convertProductStrategyIdToAidl(int xsdcId) { + if (xsdcId < AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) { + return unexpected(BAD_VALUE); + } + return xsdcId; +} + bool isDefaultAudioAttributes(const AudioAttributes& attributes) { return ((attributes.contentType == AudioContentType::UNKNOWN) && (attributes.usage == AudioUsage::UNKNOWN) && @@ -95,29 +111,26 @@ ConversionResult EngineConfigXmlConverter::convertAudioAttribut } AudioAttributes aidlAudioAttributes; if (xsdcAudioAttributes.hasContentType()) { - aidlAudioAttributes.contentType = static_cast( - xsdcAudioAttributes.getFirstContentType()->getValue()); + aidlAudioAttributes.contentType = VALUE_OR_FATAL(convertAudioContentTypeToAidl( + xsdcAudioAttributes.getFirstContentType()->getValue())); } if (xsdcAudioAttributes.hasUsage()) { - aidlAudioAttributes.usage = - static_cast(xsdcAudioAttributes.getFirstUsage()->getValue()); + aidlAudioAttributes.usage = VALUE_OR_FATAL( + convertAudioUsageToAidl(xsdcAudioAttributes.getFirstUsage()->getValue())); } if (xsdcAudioAttributes.hasSource()) { - aidlAudioAttributes.source = - static_cast(xsdcAudioAttributes.getFirstSource()->getValue()); + aidlAudioAttributes.source = VALUE_OR_FATAL( + convertAudioSourceToAidl(xsdcAudioAttributes.getFirstSource()->getValue())); } if (xsdcAudioAttributes.hasFlags()) { std::vector xsdcFlagTypeVec = xsdcAudioAttributes.getFirstFlags()->getValue(); - for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) { - if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) { - aidlAudioAttributes.flags |= 1 << (static_cast(xsdcFlagType) - 1); - } - } + aidlAudioAttributes.flags = VALUE_OR_FATAL(convertAudioFlagsToAidl(xsdcFlagTypeVec)); } if (xsdcAudioAttributes.hasBundle()) { const eng_xsd::BundleType* xsdcBundle = xsdcAudioAttributes.getFirstBundle(); - aidlAudioAttributes.tags[0] = xsdcBundle->getKey() + "=" + xsdcBundle->getValue(); + aidlAudioAttributes.tags.reserve(1); + aidlAudioAttributes.tags.push_back(xsdcBundle->getKey() + "_" + xsdcBundle->getValue()); } if (isDefaultAudioAttributes(aidlAudioAttributes)) { mDefaultProductStrategyId = std::optional{-1}; @@ -131,8 +144,10 @@ ConversionResult EngineConfigXmlConverter::convertAttri static const int kStreamTypeEnumOffset = static_cast(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) - static_cast(AudioStreamType::VOICE_CALL); - aidlAttributesGroup.streamType = static_cast( - static_cast(xsdcAttributesGroup.getStreamType()) - kStreamTypeEnumOffset); + aidlAttributesGroup.streamType = xsdcAttributesGroup.hasStreamType() + ? VALUE_OR_FATAL(convertAudioStreamTypeToAidl( + xsdcAttributesGroup.getStreamType())) + : AudioStreamType::INVALID; aidlAttributesGroup.volumeGroupName = xsdcAttributesGroup.getVolumeGroup(); if (xsdcAttributesGroup.hasAttributes_optional()) { aidlAttributesGroup.attributes = @@ -165,7 +180,8 @@ ConversionResult EngineConfigXmlConverter::convertProdu AudioHalProductStrategy aidlProductStrategy; aidlProductStrategy.id = - VALUE_OR_FATAL(convertProductStrategyNameToAidl(xsdcProductStrategy.getName())); + VALUE_OR_FATAL(convertProductStrategyIdToAidl(xsdcProductStrategy.getId())); + aidlProductStrategy.name = xsdcProductStrategy.getName(); if (xsdcProductStrategy.hasAttributesGroup()) { aidlProductStrategy.attributesGroups = VALUE_OR_FATAL( @@ -247,18 +263,15 @@ void EngineConfigXmlConverter::init() { } if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) { AudioHalEngineConfig::CapSpecificConfig capSpecificConfig; - capSpecificConfig.criteria = VALUE_OR_FATAL( - (convertWrappedCollectionToAidl( - getXsdcConfig()->getCriteria(), &eng_xsd::CriteriaType::getCriterion, - &convertCapCriterionToAidl))); - capSpecificConfig.criterionTypes = - VALUE_OR_FATAL((convertWrappedCollectionToAidl( - getXsdcConfig()->getCriterion_types(), - &eng_xsd::CriterionTypesType::getCriterion_type, - &convertCapCriterionTypeToAidl))); + capSpecificConfig.criteriaV2 = + std::make_optional<>(VALUE_OR_FATAL((convertCapCriteriaCollectionToAidl( + getXsdcConfig()->getCriteria(), getXsdcConfig()->getCriterion_types())))); + internal::CapEngineConfigXmlConverter capEngConfigConverter{ + ::android::audio_find_readable_configuration_file(kCapEngineConfigFileName)}; + if (capEngConfigConverter.getStatus() == ::android::OK) { + capSpecificConfig.domains = std::move(capEngConfigConverter.getAidlCapEngineConfig()); + } + mAidlEngineConfig.capSpecificConfig = capSpecificConfig; } } } // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/XsdcConversion.cpp b/audio/aidl/default/XsdcConversion.cpp index 172094911c..ba6110d39c 100644 --- a/audio/aidl/default/XsdcConversion.cpp +++ b/audio/aidl/default/XsdcConversion.cpp @@ -10,11 +10,21 @@ #include #include #include +#include +#include + +#include #include "core-impl/XmlConverter.h" #include "core-impl/XsdcConversion.h" +using aidl::android::hardware::audio::common::iequals; +using aidl::android::hardware::audio::common::isValidAudioMode; +using aidl::android::hardware::audio::common::isValidAudioPolicyForcedConfig; +using aidl::android::hardware::audio::common::kValidAudioModes; +using aidl::android::hardware::audio::common::kValidAudioPolicyForcedConfig; using aidl::android::media::audio::common::AudioChannelLayout; +using aidl::android::media::audio::common::AudioContentType; using aidl::android::media::audio::common::AudioDevice; using aidl::android::media::audio::common::AudioDeviceAddress; using aidl::android::media::audio::common::AudioDeviceDescription; @@ -24,22 +34,39 @@ using aidl::android::media::audio::common::AudioFormatType; using aidl::android::media::audio::common::AudioGain; using aidl::android::media::audio::common::AudioHalCapCriterion; using aidl::android::media::audio::common::AudioHalCapCriterionType; +using aidl::android::media::audio::common::AudioHalCapCriterionV2; using aidl::android::media::audio::common::AudioHalVolumeCurve; using aidl::android::media::audio::common::AudioIoFlags; +using aidl::android::media::audio::common::AudioMode; +using aidl::android::media::audio::common::AudioPolicyForcedConfig; +using aidl::android::media::audio::common::AudioPolicyForceUse; using aidl::android::media::audio::common::AudioPort; using aidl::android::media::audio::common::AudioPortConfig; using aidl::android::media::audio::common::AudioPortDeviceExt; using aidl::android::media::audio::common::AudioPortExt; using aidl::android::media::audio::common::AudioPortMixExt; using aidl::android::media::audio::common::AudioProfile; +using aidl::android::media::audio::common::AudioSource; +using aidl::android::media::audio::common::AudioStreamType; +using aidl::android::media::audio::common::AudioUsage; using ::android::BAD_VALUE; using ::android::base::unexpected; +using ::android::utilities::convertTo; namespace ap_xsd = android::audio::policy::configuration; namespace eng_xsd = android::audio::policy::engine::configuration; namespace aidl::android::hardware::audio::core::internal { +static constexpr const char kXsdcForceConfigForCommunication[] = "ForceUseForCommunication"; +static constexpr const char kXsdcForceConfigForMedia[] = "ForceUseForMedia"; +static constexpr const char kXsdcForceConfigForRecord[] = "ForceUseForRecord"; +static constexpr const char kXsdcForceConfigForDock[] = "ForceUseForDock"; +static constexpr const char kXsdcForceConfigForSystem[] = "ForceUseForSystem"; +static constexpr const char kXsdcForceConfigForHdmiSystemAudio[] = "ForceUseForHdmiSystemAudio"; +static constexpr const char kXsdcForceConfigForEncodedSurround[] = "ForceUseForEncodedSurround"; +static constexpr const char kXsdcForceConfigForVibrateRinging[] = "ForceUseForVibrateRinging"; + inline ConversionResult assertNonEmpty(const std::string& s) { if (s.empty()) { LOG(ERROR) << __func__ << " Review Audio Policy config: " @@ -51,6 +78,100 @@ inline ConversionResult assertNonEmpty(const std::string& s) { #define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s)) +ConversionResult convertAudioFlagsToAidl( + const std::vector& xsdcFlagTypeVec) { + int legacyFlagMask = 0; + for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) { + if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) { + audio_flags_mask_t legacyFlag = AUDIO_FLAG_NONE; + if (!::android::AudioFlagConverter::fromString(eng_xsd::toString(xsdcFlagType), + legacyFlag)) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " + << eng_xsd::toString(xsdcFlagType) << " is not a valid flag."; + return unexpected(BAD_VALUE); + } + legacyFlagMask |= static_cast(legacyFlag); + } + } + ConversionResult result = legacy2aidl_audio_flags_mask_t_int32_t_mask( + static_cast(legacyFlagMask)); + if (!result.ok()) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyFlagMask + << " has invalid flag(s)."; + return unexpected(BAD_VALUE); + } + return result; +} + +ConversionResult convertAudioStreamTypeToAidl(const eng_xsd::Stream& xsdcStream) { + audio_stream_type_t legacyStreamType; + if (!::android::StreamTypeConverter::fromString(eng_xsd::toString(xsdcStream), + legacyStreamType)) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " << eng_xsd::toString(xsdcStream) + << " is not a valid audio stream type."; + return unexpected(BAD_VALUE); + } + ConversionResult result = + legacy2aidl_audio_stream_type_t_AudioStreamType(legacyStreamType); + if (!result.ok()) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyStreamType + << " is not a valid audio stream type."; + return unexpected(BAD_VALUE); + } + return result; +} + +ConversionResult convertAudioSourceToAidl( + const eng_xsd::SourceEnumType& xsdcSourceType) { + audio_source_t legacySourceType; + if (!::android::SourceTypeConverter::fromString(eng_xsd::toString(xsdcSourceType), + legacySourceType)) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " + << eng_xsd::toString(xsdcSourceType) << " is not a valid audio source."; + return unexpected(BAD_VALUE); + } + ConversionResult result = legacy2aidl_audio_source_t_AudioSource(legacySourceType); + if (!result.ok()) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacySourceType + << " is not a valid audio source."; + return unexpected(BAD_VALUE); + } + return result; +} + +ConversionResult convertAudioContentTypeToAidl( + const eng_xsd::ContentType& xsdcContentType) { + audio_content_type_t legacyContentType; + if (!::android::AudioContentTypeConverter::fromString(eng_xsd::toString(xsdcContentType), + legacyContentType)) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " + << eng_xsd::toString(xsdcContentType) << " is not a valid audio content type."; + return unexpected(BAD_VALUE); + } + ConversionResult result = + legacy2aidl_audio_content_type_t_AudioContentType(legacyContentType); + if (!result.ok()) { + LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyContentType + << " is not a valid audio content type."; + return unexpected(BAD_VALUE); + } + return result; +} + +ConversionResult convertAudioUsageToAidl(const eng_xsd::UsageEnumType& xsdcUsage) { + audio_usage_t legacyUsage; + if (!::android::UsageTypeConverter::fromString(eng_xsd::toString(xsdcUsage), legacyUsage)) { + LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage."; + return unexpected(BAD_VALUE); + } + ConversionResult result = legacy2aidl_audio_usage_t_AudioUsage(legacyUsage); + if (!result.ok()) { + LOG(ERROR) << __func__ << " Review Audio Policy config, not a valid audio usage."; + return unexpected(BAD_VALUE); + } + return result; +} + ConversionResult convertAudioFormatToAidl(const std::string& xsdcFormat) { audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT); ConversionResult result = @@ -410,32 +531,240 @@ ConversionResult> convertModuleConfigToAi return result; } +ConversionResult convertForcedConfigToAidl( + const std::string& xsdcForcedConfigCriterionType) { + const auto it = std::find_if( + kValidAudioPolicyForcedConfig.begin(), kValidAudioPolicyForcedConfig.end(), + [&](const auto& config) { return toString(config) == xsdcForcedConfigCriterionType; }); + if (it == kValidAudioPolicyForcedConfig.end()) { + LOG(ERROR) << __func__ << " invalid forced config " << xsdcForcedConfigCriterionType; + return unexpected(BAD_VALUE); + } + return *it; +} + +ConversionResult convertTelephonyModeToAidl(const std::string& xsdcModeCriterionType) { + const auto it = std::find_if(kValidAudioModes.begin(), kValidAudioModes.end(), + [&xsdcModeCriterionType](const auto& mode) { + return toString(mode) == xsdcModeCriterionType; + }); + if (it == kValidAudioModes.end()) { + LOG(ERROR) << __func__ << " invalid mode " << xsdcModeCriterionType; + return unexpected(BAD_VALUE); + } + return *it; +} + +ConversionResult convertDeviceAddressToAidl(const std::string& xsdcAddress) { + return AudioDeviceAddress::make(xsdcAddress); +} + +ConversionResult getCriterionTypeByName( + const std::string& name, + const std::vector& xsdcCriterionTypesVec) { + for (const auto& xsdCriterionTypes : xsdcCriterionTypesVec) { + for (const auto& xsdcCriterionType : xsdCriterionTypes.getCriterion_type()) { + if (xsdcCriterionType.getName() == name) { + return xsdcCriterionType; + } + } + } + LOG(ERROR) << __func__ << " failed to find criterion type " << name; + return unexpected(BAD_VALUE); +} + +ConversionResult>> +convertCapCriteriaCollectionToAidl( + const std::vector& xsdcCriteriaVec, + const std::vector& xsdcCriterionTypesVec) { + std::vector> resultAidlCriterionVec; + if (xsdcCriteriaVec.empty() || xsdcCriterionTypesVec.empty()) { + LOG(ERROR) << __func__ << " empty criteria/criterionTypes"; + return unexpected(BAD_VALUE); + } + for (const auto& xsdCriteria : xsdcCriteriaVec) { + for (const auto& xsdcCriterion : xsdCriteria.getCriterion()) { + resultAidlCriterionVec.push_back( + std::optional(VALUE_OR_FATAL( + convertCapCriterionV2ToAidl(xsdcCriterion, xsdcCriterionTypesVec)))); + } + } + return resultAidlCriterionVec; +} + +ConversionResult> convertDevicesToAidl( + const eng_xsd::CriterionTypeType& xsdcDeviceCriterionType) { + if (xsdcDeviceCriterionType.getValues().empty()) { + LOG(ERROR) << __func__ << " no values provided"; + return unexpected(BAD_VALUE); + } + std::vector aidlDevices; + for (eng_xsd::ValuesType xsdcValues : xsdcDeviceCriterionType.getValues()) { + aidlDevices.reserve(xsdcValues.getValue().size()); + for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) { + if (!xsdcValue.hasAndroid_type()) { + LOG(ERROR) << __func__ << " empty android type"; + return unexpected(BAD_VALUE); + } + uint32_t integerValue; + if (!convertTo(xsdcValue.getAndroid_type(), integerValue)) { + LOG(ERROR) << __func__ << " failed to convert android type " + << xsdcValue.getAndroid_type(); + return unexpected(BAD_VALUE); + } + aidlDevices.push_back( + VALUE_OR_RETURN(legacy2aidl_audio_devices_t_AudioDeviceDescription( + static_cast(integerValue)))); + } + } + return aidlDevices; +} + +ConversionResult> convertDeviceAddressesToAidl( + const eng_xsd::CriterionTypeType& xsdcDeviceAddressesCriterionType) { + if (xsdcDeviceAddressesCriterionType.getValues().empty()) { + LOG(ERROR) << __func__ << " no values provided"; + return unexpected(BAD_VALUE); + } + std::vector aidlDeviceAddresses; + for (eng_xsd::ValuesType xsdcValues : xsdcDeviceAddressesCriterionType.getValues()) { + aidlDeviceAddresses.reserve(xsdcValues.getValue().size()); + for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) { + aidlDeviceAddresses.push_back( + AudioDeviceAddress::make(xsdcValue.getLiteral())); + } + } + return aidlDeviceAddresses; +} + +ConversionResult> convertTelephonyModesToAidl( + const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) { + if (xsdcTelephonyModeCriterionType.getValues().empty()) { + LOG(ERROR) << __func__ << " no values provided"; + return unexpected(BAD_VALUE); + } + std::vector aidlAudioModes; + for (eng_xsd::ValuesType xsdcValues : xsdcTelephonyModeCriterionType.getValues()) { + aidlAudioModes.reserve(xsdcValues.getValue().size()); + for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) { + int integerValue = xsdcValue.getNumerical(); + if (!isValidAudioMode(AudioMode(integerValue))) { + LOG(ERROR) << __func__ << " invalid audio mode " << integerValue; + return unexpected(BAD_VALUE); + } + aidlAudioModes.push_back(AudioMode(integerValue)); + } + } + return aidlAudioModes; +} + +ConversionResult> convertForcedConfigsToAidl( + const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) { + if (xsdcForcedConfigCriterionType.getValues().empty()) { + LOG(ERROR) << __func__ << " no values provided"; + return unexpected(BAD_VALUE); + } + std::vector aidlForcedConfigs; + for (eng_xsd::ValuesType xsdcValues : xsdcForcedConfigCriterionType.getValues()) { + aidlForcedConfigs.reserve(xsdcValues.getValue().size()); + for (const eng_xsd::ValueType& xsdcValue : xsdcValues.getValue()) { + int integerValue = xsdcValue.getNumerical(); + if (!isValidAudioPolicyForcedConfig(AudioPolicyForcedConfig(integerValue))) { + LOG(ERROR) << __func__ << " invalid forced config mode " << integerValue; + return unexpected(BAD_VALUE); + } + aidlForcedConfigs.push_back(AudioPolicyForcedConfig(integerValue)); + } + } + return aidlForcedConfigs; +} + +ConversionResult convertForceUseCriterionToAidl( + const std::string& xsdcCriterionName) { + if (!fastcmp(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication, + strlen(kXsdcForceConfigForCommunication))) { + return AudioPolicyForceUse::COMMUNICATION; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia, + strlen(kXsdcForceConfigForMedia))) { + return AudioPolicyForceUse::MEDIA; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord, + strlen(kXsdcForceConfigForRecord))) { + return AudioPolicyForceUse::RECORD; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForDock, + strlen(kXsdcForceConfigForDock))) { + return AudioPolicyForceUse::DOCK; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem, + strlen(kXsdcForceConfigForSystem))) { + return AudioPolicyForceUse::SYSTEM; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio, + strlen(kXsdcForceConfigForHdmiSystemAudio))) { + return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround, + strlen(kXsdcForceConfigForEncodedSurround))) { + return AudioPolicyForceUse::ENCODED_SURROUND; + } + if (!fasticmp(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging, + strlen(kXsdcForceConfigForVibrateRinging))) { + return AudioPolicyForceUse::VIBRATE_RINGING; + } + LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName; + return unexpected(BAD_VALUE); +} + +ConversionResult convertCapCriterionV2ToAidl( + const eng_xsd::CriterionType& xsdcCriterion, + const std::vector& xsdcCriterionTypesVec) { + eng_xsd::CriterionTypeType xsdcCriterionType = + VALUE_OR_RETURN(getCriterionTypeByName(xsdcCriterion.getType(), xsdcCriterionTypesVec)); + std::string defaultLiteralValue = + xsdcCriterion.has_default() ? xsdcCriterion.get_default() : ""; + using Tag = AudioHalCapCriterionV2::Tag; + if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevices))) { + return AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType))); + } + if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevices))) { + return AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType))); + } + if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevicesAddresses))) { + return AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType))); + } + if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevicesAddresses))) { + return AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType))); + } + if (iequals(xsdcCriterion.getName(), toString(Tag::telephonyMode))) { + return AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertTelephonyModesToAidl(xsdcCriterionType))); + } + if (!fastcmp(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse, + strlen(kXsdcForceConfigForUse))) { + return AudioHalCapCriterionV2::make( + VALUE_OR_RETURN(convertForceUseCriterionToAidl(xsdcCriterion.getName())), + VALUE_OR_RETURN(convertForcedConfigsToAidl(xsdcCriterionType))); + } + LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName(); + return unexpected(BAD_VALUE); +} + ConversionResult convertCapCriterionToAidl( const eng_xsd::CriterionType& xsdcCriterion) { AudioHalCapCriterion aidlCapCriterion; aidlCapCriterion.name = xsdcCriterion.getName(); aidlCapCriterion.criterionTypeName = xsdcCriterion.getType(); - aidlCapCriterion.defaultLiteralValue = xsdcCriterion.get_default(); + aidlCapCriterion.defaultLiteralValue = + xsdcCriterion.has_default() ? xsdcCriterion.get_default() : ""; return aidlCapCriterion; } -ConversionResult convertCriterionTypeValueToAidl( - const eng_xsd::ValueType& xsdcCriterionTypeValue) { - return xsdcCriterionTypeValue.getLiteral(); -} - -ConversionResult convertCapCriterionTypeToAidl( - const eng_xsd::CriterionTypeType& xsdcCriterionType) { - AudioHalCapCriterionType aidlCapCriterionType; - aidlCapCriterionType.name = xsdcCriterionType.getName(); - aidlCapCriterionType.isInclusive = !(static_cast(xsdcCriterionType.getType())); - aidlCapCriterionType.values = VALUE_OR_RETURN( - (convertWrappedCollectionToAidl( - xsdcCriterionType.getValues(), &eng_xsd::ValuesType::getValue, - &convertCriterionTypeValueToAidl))); - return aidlCapCriterionType; -} - ConversionResult convertCurvePointToAidl( const std::string& xsdcCurvePoint) { AudioHalVolumeCurve::CurvePoint aidlCurvePoint{}; diff --git a/audio/aidl/default/config/audioPolicy/capengine/Android.bp b/audio/aidl/default/config/audioPolicy/capengine/Android.bp new file mode 100644 index 0000000000..cb999236d3 --- /dev/null +++ b/audio/aidl/default/config/audioPolicy/capengine/Android.bp @@ -0,0 +1,17 @@ +package { + default_team: "trendy_team_android_media_audio_framework", + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +xsd_config { + name: "audio_policy_capengine_configuration_aidl_default", + srcs: ["PolicyConfigurableDomains.xsd"], + package_name: "android.audio.policy.capengine.configuration", + nullability: true, + root_elements: ["ConfigurableDomains"], +} diff --git a/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd b/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd new file mode 100644 index 0000000000..4e7c0bb115 --- /dev/null +++ b/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd @@ -0,0 +1,467 @@ + + + + + + + See http://www.w3.org/XML/1998/namespace.html and + http://www.w3.org/TR/REC-xml for information about this namespace. + + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + + Note that local names in this namespace are intended to be defined + only by the World Wide Web Consortium or its subgroups. The + following names are currently defined in this namespace and should + not be used with conflicting semantics by any Working Group, + specification, or document instance: + + base (as an attribute name): denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification. + + id (as an attribute name): denotes an attribute whose value + should be interpreted as if declared to be of type ID. + The xml:id specification is not yet a W3C Recommendation, + but this attribute is included here to facilitate experimentation + with the mechanisms it proposes. Note that it is _not_ included + in the specialAttrs attribute group. + + lang (as an attribute name): denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification. + + space (as an attribute name): denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification. + + Father (in any context at all): denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + + In appreciation for his vision, leadership and dedication + the W3C XML Plenary on this 10th day of February, 2000 + reserves for Jon Bosak in perpetuity the XML name + xml:Father + + + + + This schema defines attributes and an attribute group + suitable for use by + schemas wishing to allow xml:base, xml:lang, xml:space or xml:id + attributes on elements they define. + + To enable this, such a schema must import this schema + for the XML namespace, e.g. as follows: + <schema . . .> + . . . + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2005/08/xml.xsd"/> + + Subsequently, qualified reference to any of the attributes + or the group defined below will have the desired effect, e.g. + + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + + will define a type which will schema-validate an instance + element with any of those attributes + + + + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + http://www.w3.org/2005/08/xml.xsd. + At the date of issue it can also be found at + http://www.w3.org/2001/xml.xsd. + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML Schema + itself, or with the XML namespace itself. In other words, if the XML + Schema or XML namespaces change, the version of this document at + http://www.w3.org/2001/xml.xsd will change + accordingly; the version at + http://www.w3.org/2005/08/xml.xsd will not change. + + + + + + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. See + RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry + at http://www.iana.org/assignments/lang-tag-apps.htm for + further information. + + The union allows for the 'un-declaration' of xml:lang with + the empty string. + + + + + + + + + + + + + + + + + + + + + + + + See http://www.w3.org/TR/xmlbase/ for + information about this attribute. + + + + + + See http://www.w3.org/TR/xml-id/ for + information about this attribute. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/current.txt b/audio/aidl/default/config/audioPolicy/capengine/api/current.txt new file mode 100644 index 0000000000..481abbf9e7 --- /dev/null +++ b/audio/aidl/default/config/audioPolicy/capengine/api/current.txt @@ -0,0 +1,264 @@ +// Signature format: 2.0 +package android.audio.policy.capengine.configuration { + + public class BitParameterBlockType { + ctor public BitParameterBlockType(); + method @Nullable public java.util.List getBitParameter(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName(); + method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType); + } + + public class BooleanParameterType { + ctor public BooleanParameterType(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType); + method public void setValue(@Nullable String); + } + + public class ComponentType { + ctor public ComponentType(); + method @Nullable public String getName(); + method @Nullable public java.util.List getSubsystem_optional(); + method public void setName(@Nullable String); + } + + public class CompoundRuleType { + ctor public CompoundRuleType(); + method @Nullable public android.audio.policy.capengine.configuration.CompoundRuleType getCompoundRule_optional(); + method @Nullable public android.audio.policy.capengine.configuration.SelectionCriterionRuleType getSelectionCriterionRule_optional(); + method @Nullable public android.audio.policy.capengine.configuration.TypeEnum getType(); + method public void setCompoundRule_optional(@Nullable android.audio.policy.capengine.configuration.CompoundRuleType); + method public void setSelectionCriterionRule_optional(@Nullable android.audio.policy.capengine.configuration.SelectionCriterionRuleType); + method public void setType(@Nullable android.audio.policy.capengine.configuration.TypeEnum); + } + + public class ConfigurableDomainType { + ctor public ConfigurableDomainType(); + method @Nullable public android.audio.policy.capengine.configuration.ConfigurableElementsType getConfigurableElements(); + method @Nullable public android.audio.policy.capengine.configuration.ConfigurationsType getConfigurations(); + method @Nullable public String getName(); + method @Nullable public boolean getSequenceAware(); + method @Nullable public android.audio.policy.capengine.configuration.SettingsType getSettings(); + method public void setConfigurableElements(@Nullable android.audio.policy.capengine.configuration.ConfigurableElementsType); + method public void setConfigurations(@Nullable android.audio.policy.capengine.configuration.ConfigurationsType); + method public void setName(@Nullable String); + method public void setSequenceAware(@Nullable boolean); + method public void setSettings(@Nullable android.audio.policy.capengine.configuration.SettingsType); + } + + public class ConfigurableDomains { + ctor public ConfigurableDomains(); + method @Nullable public java.util.List getConfigurableDomain(); + method @Nullable public String getSystemClassName(); + method public void setSystemClassName(@Nullable String); + } + + public class ConfigurableElementSettingsType { + ctor public ConfigurableElementSettingsType(); + method @Nullable public android.audio.policy.capengine.configuration.BitParameterBlockType getBitParameterBlock_optional(); + method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getBitParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.BooleanParameterType getBooleanParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.EnumParameterType getEnumParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFixedPointParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFloatingPointParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getIntegerParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterBlockType getParameterBlock_optional(); + method @Nullable public String getPath(); + method @Nullable public android.audio.policy.capengine.configuration.StringParameterType getStringParameter_optional(); + method public void setBitParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.BitParameterBlockType); + method public void setBitParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType); + method public void setBooleanParameter_optional(@Nullable android.audio.policy.capengine.configuration.BooleanParameterType); + method public void setEnumParameter_optional(@Nullable android.audio.policy.capengine.configuration.EnumParameterType); + method public void setFixedPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType); + method public void setFloatingPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType); + method public void setIntegerParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType); + method public void setParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.ParameterBlockType); + method public void setPath(@Nullable String); + method public void setStringParameter_optional(@Nullable android.audio.policy.capengine.configuration.StringParameterType); + } + + public class ConfigurableElementsType { + ctor public ConfigurableElementsType(); + method @Nullable public java.util.List getConfigurableElement(); + } + + public static class ConfigurableElementsType.ConfigurableElement { + ctor public ConfigurableElementsType.ConfigurableElement(); + method @Nullable public String getPath(); + method public void setPath(@Nullable String); + } + + public class ConfigurationsType { + ctor public ConfigurationsType(); + method @Nullable public java.util.List getConfiguration(); + } + + public static class ConfigurationsType.Configuration { + ctor public ConfigurationsType.Configuration(); + method @Nullable public android.audio.policy.capengine.configuration.CompoundRuleType getCompoundRule(); + method @Nullable public String getName(); + method public void setCompoundRule(@Nullable android.audio.policy.capengine.configuration.CompoundRuleType); + method public void setName(@Nullable String); + } + + public class EnumParameterType { + ctor public EnumParameterType(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType); + method public void setValue(@Nullable String); + } + + public class IntegerParameterType { + ctor public IntegerParameterType(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType); + method public void setValue(@Nullable String); + } + + public enum LangEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.audio.policy.capengine.configuration.LangEnum EMPTY; + } + + public enum MatchesWhenEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Excludes; + enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Includes; + enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum Is; + enum_constant public static final android.audio.policy.capengine.configuration.MatchesWhenEnum IsNot; + } + + public class ParameterBlockType { + ctor public ParameterBlockType(); + method @Nullable public android.audio.policy.capengine.configuration.BitParameterBlockType getBitParameterBlock_optional(); + method @Nullable public android.audio.policy.capengine.configuration.BooleanParameterType getBooleanParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.EnumParameterType getEnumParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFixedPointParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.PointParameterType getFloatingPointParameter_optional(); + method @Nullable public android.audio.policy.capengine.configuration.IntegerParameterType getIntegerParameter_optional(); + method @Nullable public String getName(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterBlockType getParameterBlock_optional(); + method @Nullable public android.audio.policy.capengine.configuration.StringParameterType getStringParameter_optional(); + method public void setBitParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.BitParameterBlockType); + method public void setBooleanParameter_optional(@Nullable android.audio.policy.capengine.configuration.BooleanParameterType); + method public void setEnumParameter_optional(@Nullable android.audio.policy.capengine.configuration.EnumParameterType); + method public void setFixedPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType); + method public void setFloatingPointParameter_optional(@Nullable android.audio.policy.capengine.configuration.PointParameterType); + method public void setIntegerParameter_optional(@Nullable android.audio.policy.capengine.configuration.IntegerParameterType); + method public void setName(@Nullable String); + method public void setParameterBlock_optional(@Nullable android.audio.policy.capengine.configuration.ParameterBlockType); + method public void setStringParameter_optional(@Nullable android.audio.policy.capengine.configuration.StringParameterType); + } + + public enum ParameterNameEnumType { + method @NonNull public String getRawName(); + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ambient; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType anlg_dock_headset; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType aux_line; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType back_mic; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_broadcast; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_headset; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ble_speaker; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp_headphones; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_a2dp_speaker; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_ble; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco_carkit; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bluetooth_sco_headset; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType builtin_mic; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType bus; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType communication; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType device_address; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType dgtl_dock_headset; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType earpiece; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType echo_canceller; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType echo_reference; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType fm; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType fm_tuner; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi_arc; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hdmi_earc; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType hearing_aid; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType ip; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType line; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType loopback; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType proxy; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType remote_submix; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType spdif; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType speaker; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType speaker_safe; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType stub; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType telephony_rx; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType telephony_tx; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType tv_tuner; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_accessory; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_device; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType usb_headset; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType volume_profile; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType wired_headphone; + enum_constant public static final android.audio.policy.capengine.configuration.ParameterNameEnumType wired_headset; + } + + public class PointParameterType { + ctor public PointParameterType(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType); + method public void setValue(@Nullable String); + } + + public class SelectionCriterionRuleType { + ctor public SelectionCriterionRuleType(); + method @Nullable public android.audio.policy.capengine.configuration.MatchesWhenEnum getMatchesWhen(); + method @Nullable public String getSelectionCriterion(); + method @Nullable public String getValue(); + method public void setMatchesWhen(@Nullable android.audio.policy.capengine.configuration.MatchesWhenEnum); + method public void setSelectionCriterion(@Nullable String); + method public void setValue(@Nullable String); + } + + public class SettingsType { + ctor public SettingsType(); + method @Nullable public java.util.List getConfiguration(); + } + + public static class SettingsType.Configuration { + ctor public SettingsType.Configuration(); + method @Nullable public java.util.List getConfigurableElement(); + method @Nullable public String getName(); + method public void setName(@Nullable String); + } + + public enum SpaceEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.audio.policy.capengine.configuration.SpaceEnum _default; + enum_constant public static final android.audio.policy.capengine.configuration.SpaceEnum preserve; + } + + public class StringParameterType { + ctor public StringParameterType(); + method @Nullable public android.audio.policy.capengine.configuration.ParameterNameEnumType getName(); + method @Nullable public String getValue(); + method public void setName(@Nullable android.audio.policy.capengine.configuration.ParameterNameEnumType); + method public void setValue(@Nullable String); + } + + public enum TypeEnum { + method @NonNull public String getRawName(); + enum_constant public static final android.audio.policy.capengine.configuration.TypeEnum All; + enum_constant public static final android.audio.policy.capengine.configuration.TypeEnum Any; + } + + public class XmlParser { + ctor public XmlParser(); + method @Nullable public static android.audio.policy.capengine.configuration.ConfigurableDomains readConfigurableDomains(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; + } + +} + diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/last_current.txt b/audio/aidl/default/config/audioPolicy/capengine/api/last_current.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/last_removed.txt b/audio/aidl/default/config/audioPolicy/capengine/api/last_removed.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/audio/aidl/default/config/audioPolicy/capengine/api/removed.txt b/audio/aidl/default/config/audioPolicy/capengine/api/removed.txt new file mode 100644 index 0000000000..d802177e24 --- /dev/null +++ b/audio/aidl/default/config/audioPolicy/capengine/api/removed.txt @@ -0,0 +1 @@ +// Signature format: 2.0 diff --git a/audio/aidl/default/config/audioPolicy/engine/api/current.txt b/audio/aidl/default/config/audioPolicy/engine/api/current.txt index 063b05dd61..8e0e9a232d 100644 --- a/audio/aidl/default/config/audioPolicy/engine/api/current.txt +++ b/audio/aidl/default/config/audioPolicy/engine/api/current.txt @@ -162,7 +162,9 @@ package android.audio.policy.engine.configuration { public static class ProductStrategies.ProductStrategy { ctor public ProductStrategies.ProductStrategy(); method @Nullable public java.util.List getAttributesGroup(); + method @Nullable public int getId(); method @Nullable public String getName(); + method public void setId(@Nullable int); method public void setName(@Nullable String); } diff --git a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd index 40396bb9b9..e2508ead6a 100644 --- a/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd +++ b/audio/aidl/default/config/audioPolicy/engine/audio_policy_engine_configuration.xsd @@ -105,6 +105,7 @@ + @@ -188,6 +189,19 @@ + + + Criterion type is provided as a tuple of 'human readable' string (referred as the + literal part, that will allow to express 'human readable' rules, numerical value + associated in order to improve performances of the parameter framework library used, + and an optional android type. + This android type is reserved for device type mapping with parameter framework + representation on a bitfield (Only one bit is expected to represent a device) and + android representation of a type that may use several bits. + The lookup table will allow wrap android device type to parameter framework device + types data model. + + diff --git a/audio/aidl/default/include/core-impl/CapEngineConfigXmlConverter.h b/audio/aidl/default/include/core-impl/CapEngineConfigXmlConverter.h new file mode 100644 index 0000000000..e5da4f4b1c --- /dev/null +++ b/audio/aidl/default/include/core-impl/CapEngineConfigXmlConverter.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include + +#include +#include + +#include "EngineConfigXmlConverter.h" + +namespace aidl::android::hardware::audio::core::internal { + +namespace capconfiguration = ::android::audio::policy::capengine::configuration; +namespace aidlcommon = ::aidl::android::media::audio::common; + +class CapEngineConfigXmlConverter { + public: + explicit CapEngineConfigXmlConverter(const std::string& configFilePath) + : mConverter(configFilePath, &capconfiguration::readConfigurableDomains) { + if (mConverter.getXsdcConfig()) { + init(); + } + } + std::string getError() const { return mConverter.getError(); } + ::android::status_t getStatus() const { return mConverter.getStatus(); } + + std::optional< + std::vector>>& + getAidlCapEngineConfig(); + + private: + ConversionResult> convertSettingToAidl( + const capconfiguration::SettingsType::Configuration& xsdcSetting); + + ConversionResult> convertConfigurationsToAidl( + const std::vector& xsdcConfigurationsVec, + const std::vector& xsdcSettingsVec); + + ConversionResult convertConfigurationToAidl( + const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration, + const capconfiguration::SettingsType::Configuration& xsdcSettingConfiguration); + + ConversionResult convertParamToAidl( + const capconfiguration::ConfigurableElementSettingsType& element); + + ConversionResult convertConfigurationToAidl( + const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration); + ConversionResult convertConfigurableDomainToAidl( + const capconfiguration::ConfigurableDomainType& xsdcConfigurableDomain); + + const std::optional& getXsdcConfig() { + return mConverter.getXsdcConfig(); + } + void init(); + + std::optional>> mAidlCapDomains; + XmlConverter mConverter; +}; +} // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h index 22ac8cb42c..211c16f39c 100644 --- a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h +++ b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h @@ -59,6 +59,7 @@ class EngineConfigXmlConverter { ConversionResult<::aidl::android::media::audio::common::AudioHalProductStrategy> convertProductStrategyToAidl(const ::android::audio::policy::engine::configuration:: ProductStrategies::ProductStrategy& xsdcProductStrategy); + ConversionResult convertProductStrategyIdToAidl(int xsdcId); ConversionResult convertProductStrategyNameToAidl( const std::string& xsdcProductStrategyName); ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve> diff --git a/audio/aidl/default/include/core-impl/XmlConverter.h b/audio/aidl/default/include/core-impl/XmlConverter.h index 68e6b8e3a3..4b99d72525 100644 --- a/audio/aidl/default/include/core-impl/XmlConverter.h +++ b/audio/aidl/default/include/core-impl/XmlConverter.h @@ -105,6 +105,19 @@ static ConversionResult> convertWrappedCollectionToAidl( return resultAidlTypeVec; } +template +static ConversionResult>> convertCollectionToAidlOptionalValues( + const std::vector& xsdcTypeVec, + std::function(const X&)> convertToAidl) { + std::vector> resultAidlTypeVec; + resultAidlTypeVec.reserve(xsdcTypeVec.size()); + for (const X& xsdcType : xsdcTypeVec) { + resultAidlTypeVec.push_back( + std::optional(std::move(VALUE_OR_FATAL(convertToAidl(xsdcType))))); + } + return resultAidlTypeVec; +} + template static ConversionResult> convertCollectionToAidl( const std::vector& xsdcTypeVec, diff --git a/audio/aidl/default/include/core-impl/XsdcConversion.h b/audio/aidl/default/include/core-impl/XsdcConversion.h index 30dc8b635b..e855a3efe4 100644 --- a/audio/aidl/default/include/core-impl/XsdcConversion.h +++ b/audio/aidl/default/include/core-impl/XsdcConversion.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -15,15 +16,40 @@ namespace aidl::android::hardware::audio::core::internal { -ConversionResult<::aidl::android::media::audio::common::AudioHalCapCriterion> -convertCapCriterionToAidl( - const ::android::audio::policy::engine::configuration::CriterionType& xsdcCriterion); -ConversionResult<::aidl::android::media::audio::common::AudioHalCapCriterionType> -convertCapCriterionTypeToAidl( - const ::android::audio::policy::engine::configuration::CriterionTypeType& - xsdcCriterionType); -ConversionResult<::aidl::android::media::audio::common::AudioHalVolumeCurve::CurvePoint> -convertCurvePointToAidl(const std::string& xsdcCurvePoint); +namespace engineconfiguration = ::android::audio::policy::engine::configuration; +namespace aidlaudiocommon = ::aidl::android::media::audio::common; + +static constexpr const char kXsdcForceConfigForUse[] = "ForceUseFor"; + +ConversionResult convertForceUseCriterionToAidl( + const std::string& xsdcCriterionName); +ConversionResult convertForcedConfigToAidl( + const std::string& xsdcForcedConfigCriterionType); +ConversionResult convertDeviceAddressToAidl( + const std::string& xsdcAddress); +ConversionResult convertTelephonyModeToAidl( + const std::string& xsdcModeCriterionType); +ConversionResult convertDeviceTypeToAidl( + const std::string& xType); +ConversionResult>> +convertCapCriteriaCollectionToAidl( + const std::vector& xsdcCriteriaVec, + const std::vector& xsdcCriterionTypesVec); +ConversionResult convertCapCriterionV2ToAidl( + const engineconfiguration::CriterionType& xsdcCriterion, + const std::vector& xsdcCriterionTypesVec); +ConversionResult convertCurvePointToAidl( + const std::string& xsdcCurvePoint); ConversionResult> convertModuleConfigToAidl( const ::android::audio::policy::configuration::Modules::Module& moduleConfig); +ConversionResult convertAudioUsageToAidl( + const engineconfiguration::UsageEnumType& xsdcUsage); +ConversionResult convertAudioContentTypeToAidl( + const engineconfiguration::ContentType& xsdcContentType); +ConversionResult convertAudioSourceToAidl( + const engineconfiguration::SourceEnumType& xsdcSourceType); +ConversionResult convertAudioStreamTypeToAidl( + const engineconfiguration::Stream& xsdStreamType); +ConversionResult convertAudioFlagsToAidl( + const std::vector& xsdcFlagTypeVec); } // namespace aidl::android::hardware::audio::core::internal diff --git a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp index f82e8e57c6..25fcd46825 100644 --- a/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp +++ b/audio/aidl/vts/VtsHalAudioCoreConfigTargetTest.cpp @@ -38,16 +38,24 @@ using aidl::android::hardware::audio::common::isDefaultAudioFormat; using aidl::android::hardware::audio::core::IConfig; using aidl::android::hardware::audio::core::SurroundSoundConfig; using aidl::android::media::audio::common::AudioAttributes; +using aidl::android::media::audio::common::AudioDeviceAddress; +using aidl::android::media::audio::common::AudioDeviceDescription; using aidl::android::media::audio::common::AudioFlag; using aidl::android::media::audio::common::AudioFormatDescription; using aidl::android::media::audio::common::AudioFormatType; using aidl::android::media::audio::common::AudioHalAttributesGroup; -using aidl::android::media::audio::common::AudioHalCapCriterion; -using aidl::android::media::audio::common::AudioHalCapCriterionType; +using aidl::android::media::audio::common::AudioHalCapConfiguration; +using aidl::android::media::audio::common::AudioHalCapCriterionV2; +using aidl::android::media::audio::common::AudioHalCapDomain; +using aidl::android::media::audio::common::AudioHalCapParameter; +using aidl::android::media::audio::common::AudioHalCapRule; using aidl::android::media::audio::common::AudioHalEngineConfig; using aidl::android::media::audio::common::AudioHalProductStrategy; using aidl::android::media::audio::common::AudioHalVolumeCurve; using aidl::android::media::audio::common::AudioHalVolumeGroup; +using aidl::android::media::audio::common::AudioMode; +using aidl::android::media::audio::common::AudioPolicyForceUse; +using aidl::android::media::audio::common::AudioPolicyForcedConfig; using aidl::android::media::audio::common::AudioProductStrategyType; using aidl::android::media::audio::common::AudioSource; using aidl::android::media::audio::common::AudioStreamType; @@ -256,48 +264,318 @@ class AudioCoreConfig : public testing::TestWithParam { } /** - * Verify defaultLiteralValue is empty for inclusive criterion. + * Verify criterion provides a non empty value list. + * Verify logic rule provided is the expected one. */ - void ValidateAudioHalCapCriterion(const AudioHalCapCriterion& criterion, - const AudioHalCapCriterionType& criterionType) { - if (criterionType.isInclusive) { - EXPECT_TRUE(criterion.defaultLiteralValue.empty()); + void ValidateAudioHalCapCriterion(const AudioHalCapCriterionV2& criterionV2) { + switch (criterionV2.getTag()) { + case AudioHalCapCriterionV2::availableInputDevices: { + auto criterion = criterionV2.get(); + EXPECT_FALSE(criterion.values.empty()); + EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE); + break; + } + case AudioHalCapCriterionV2::availableOutputDevices: { + auto criterion = criterionV2.get(); + EXPECT_FALSE(criterion.values.empty()); + EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE); + break; + } + case AudioHalCapCriterionV2::availableInputDevicesAddresses: { + auto criterion = + criterionV2.get(); + EXPECT_FALSE(criterion.values.empty()); + EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE); + break; + } + case AudioHalCapCriterionV2::availableOutputDevicesAddresses: { + auto criterion = + criterionV2.get(); + EXPECT_FALSE(criterion.values.empty()); + EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE); + break; + } + case AudioHalCapCriterionV2::telephonyMode: { + auto criterion = criterionV2.get(); + EXPECT_FALSE(criterion.values.empty()); + EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE); + break; + } + case AudioHalCapCriterionV2::forceConfigForUse: { + auto criterion = criterionV2.get(); + EXPECT_FALSE(criterion.values.empty()); + EXPECT_EQ(criterion.logic, AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE); + break; + } + default: + ADD_FAILURE() << "Invalid criterion tag " << toString(criterionV2.getTag()); } } /** - * Verify values only contain alphanumeric characters. + * Verify the rule involve the right matching logic according to the criterion logic. + * @param matchingRule logic followed by the rule + * @param logicalDisjunction logic exposed by the criterion */ - void ValidateAudioHalCapCriterionType(const AudioHalCapCriterionType& criterionType) { - auto isNotAlnum = [](const char& c) { return !isalnum(c); }; - for (const std::string& value : criterionType.values) { - EXPECT_EQ(find_if(value.begin(), value.end(), isNotAlnum), value.end()); + void ValidateAudioHalCapRuleMatchingRule( + const AudioHalCapRule::MatchingRule matchingRule, + const AudioHalCapCriterionV2::LogicalDisjunction logicalDisjunction) { + if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE) { + EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::EXCLUDES || + matchingRule == AudioHalCapRule::MatchingRule::INCLUDES); + } else if (logicalDisjunction == AudioHalCapCriterionV2::LogicalDisjunction::EXCLUSIVE) { + EXPECT_TRUE(matchingRule == AudioHalCapRule::MatchingRule::IS || + matchingRule == AudioHalCapRule::MatchingRule::IS_NOT); + } else { + ADD_FAILURE() << "Invalid criterion Logical rule"; } } /** - * Verify each criterionType has a unique name. - * Verify each criterion has a unique name. - * Verify each criterion maps to a criterionType. - * Verify each criterionType is used in a criterion. - * Validate contained types. + * Verify that the value and the matching rule are supported by the given criterion + */ + template + void validateAudioHalCapRule(CriterionV2 criterionV2, Value value, + const AudioHalCapRule::MatchingRule matchingRule) { + ValidateAudioHalCapRuleMatchingRule(matchingRule, criterionV2.logic); + EXPECT_FALSE(criterionV2.values.empty()); + auto values = criterionV2.values; + auto valueIt = find_if(values.begin(), values.end(), + [&](const auto& typedValue) { return typedValue == value; }); + EXPECT_NE(valueIt, values.end()); + } + + /** + * Verify rule involves a supported criterion. + * Verify rule involves supported logic keyword according to logic rule exposed by the + * criterion. + * Verify rule involves a value supported by the associated criterion. + */ + void ValidateAudioHalConfigurationRule( + const AudioHalCapRule& rule, + const std::vector>& criteria) { + const auto& compoundRule = rule.compoundRule; + using TypeTag = AudioHalCapCriterionV2::Type::Tag; + if (rule.nestedRules.empty() && rule.criterionRules.empty()) { + EXPECT_EQ(compoundRule, AudioHalCapRule::CompoundRule::ALL); + } + EXPECT_TRUE(compoundRule == AudioHalCapRule::CompoundRule::ANY || + compoundRule == AudioHalCapRule::CompoundRule::ALL); + for (const auto& nestedRule : rule.nestedRules) { + ValidateAudioHalConfigurationRule(nestedRule, criteria); + } + for (const auto& criterionRule : rule.criterionRules) { + auto selectionCriterion = criterionRule.criterion; + auto criterionValue = criterionRule.criterionTypeValue; + auto matchesWhen = criterionRule.matchingRule; + auto criteriaIt = find_if(criteria.begin(), criteria.end(), [&](const auto& criterion) { + return criterion.has_value() && + criterion.value().getTag() == selectionCriterion.getTag(); + }); + EXPECT_NE(criteriaIt, criteria.end()) + << " Invalid rule criterion " << toString(selectionCriterion.getTag()); + AudioHalCapCriterionV2 matchingCriterion = (*criteriaIt).value(); + switch (selectionCriterion.getTag()) { + case AudioHalCapCriterionV2::availableInputDevices: { + EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesType); + validateAudioHalCapRule( + matchingCriterion.get(), + criterionValue.get(), matchesWhen); + break; + } + case AudioHalCapCriterionV2::availableOutputDevices: { + EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesType); + validateAudioHalCapRule( + matchingCriterion.get(), + criterionValue.get(), matchesWhen); + break; + } + case AudioHalCapCriterionV2::availableInputDevicesAddresses: { + EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesAddressesType); + validateAudioHalCapRule( + matchingCriterion + .get(), + criterionValue.get(), + matchesWhen); + break; + } + case AudioHalCapCriterionV2::availableOutputDevicesAddresses: { + EXPECT_EQ(criterionValue.getTag(), TypeTag::availableDevicesAddressesType); + validateAudioHalCapRule( + matchingCriterion + .get(), + criterionValue.get(), + matchesWhen); + break; + } + case AudioHalCapCriterionV2::telephonyMode: { + EXPECT_EQ(criterionValue.getTag(), TypeTag::telephonyModeType); + validateAudioHalCapRule( + matchingCriterion.get(), + criterionValue.get(), matchesWhen); + break; + } + case AudioHalCapCriterionV2::forceConfigForUse: { + EXPECT_EQ(criterionValue.getTag(), TypeTag::forcedConfigType); + validateAudioHalCapRule( + matchingCriterion + .get(), + criterionValue.get(), matchesWhen); + break; + } + default: + break; + } + } + } + + /** + * Get the number of occurrence of a given parameter within a given vector of parameter. + * It just take into account the parameter, not its associated value. + * @param parameter to consider + * @param domainParameters to check against + * @return matching occurrence of the parameter within the provided vector. + */ + size_t countsParameter(const AudioHalCapParameter& parameter, + const std::vector& domainParameters) { + size_t count = 0; + for (const auto& domainParameter : domainParameters) { + if (domainParameter.getTag() != parameter.getTag()) { + continue; + } + switch (domainParameter.getTag()) { + case AudioHalCapParameter::selectedStrategyDevice: { + auto typedDomainParam = + domainParameter.get(); + auto typedParam = parameter.get(); + if (typedDomainParam.id == typedParam.id && + typedDomainParam.device == typedParam.device) { + count += 1; + } + break; + } + case AudioHalCapParameter::strategyDeviceAddress: { + auto typedDomainParam = + domainParameter.get(); + auto typedParam = parameter.get(); + if (typedDomainParam.id == typedParam.id) { + count += 1; + } + break; + } + case AudioHalCapParameter::selectedInputSourceDevice: { + auto typedDomainParam = + domainParameter.get(); + auto typedParam = + parameter.get(); + if (typedDomainParam.inputSource == typedParam.inputSource && + typedDomainParam.device == typedParam.device) { + count += 1; + } + break; + } + case AudioHalCapParameter::streamVolumeProfile: { + auto typedDomainParam = + domainParameter.get(); + auto typedParam = parameter.get(); + if (typedDomainParam.stream == typedParam.stream) { + count += 1; + } + break; + } + default: + break; + } + } + return count; + } + + /** + * Verify each configuration has unique name within a domain + * Verify no duplicate parameter within a domain. + * Verify that each configuration has no duplicated parameter. + * Verify that each configuration has an associated value for all parameter within a domain. + */ + void ValidateAudioHalCapDomain( + const AudioHalCapDomain& domain, + const std::vector>& criteria) { + std::unordered_set configurationNames; + for (const AudioHalCapConfiguration& configuration : domain.configurations) { + EXPECT_TRUE(configurationNames.insert(configuration.name).second); + ValidateAudioHalConfigurationRule(configuration.rule, criteria); + } + auto domainParameters = domain.configurations[0].parameterSettings; + for (const auto& settingParameter : domainParameters) { + EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters)) + << "Duplicated parameter within domain " << domain.name << " configuration " + << domain.configurations[0].name << " for parameter " + << settingParameter.toString(); + } + for (const auto& configuration : domain.configurations) { + auto configurationParameters = configuration.parameterSettings; + for (const auto& configurationParameter : configurationParameters) { + EXPECT_EQ(1ul, countsParameter(configurationParameter, configurationParameters)) + << "Duplicated parameter within domain " << domain.name << " configuration " + << configuration.name << " for parameter " + << configurationParameter.toString(); + } + EXPECT_EQ(domainParameters.size(), configurationParameters.size()); + for (const auto& settingParameter : configuration.parameterSettings) { + EXPECT_EQ(1ul, countsParameter(settingParameter, domainParameters)) + << "Confiugration " << configuration.name << " within domain " + << domain.name << " exposes invalid parameter " + << settingParameter.toString(); + ; + } + } + } + + /** + * Verify each domain has a unique name. + * Verify that a given parameter does not appear in more than one domain. + */ + void ValidateAudioHalCapDomains( + const std::vector>& domains, + const std::vector>& criteria) { + std::unordered_map domainMap; + std::vector allDomainParameters; + for (const auto& domain : domains) { + EXPECT_TRUE(domain.has_value()); + EXPECT_FALSE(domain.value().configurations.empty()); + auto domainParameters = domain.value().configurations[0].parameterSettings; + for (const auto& domainParameter : domainParameters) { + EXPECT_EQ(0ul, countsParameter(domainParameter, allDomainParameters)) + << "Duplicated parameter in domain " << domain.value().name + << " for parameter " << domainParameter.toString(); + allDomainParameters.push_back(domainParameter); + } + EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapDomain(domain.value(), criteria)); + EXPECT_TRUE(domainMap.insert({domain.value().name, domain.value()}).second); + } + } + + /** + * Verify unique criterion is provided for a given Tag, except for ForceUse + * Verify unique forceUse criterion are provided for usage + * Verify each criterion is validating. + * Verify domains. */ void ValidateCapSpecificConfig(const AudioHalEngineConfig::CapSpecificConfig& capCfg) { - EXPECT_FALSE(capCfg.criteria.empty()); - EXPECT_FALSE(capCfg.criterionTypes.empty()); - std::unordered_map criterionTypeMap; - for (const AudioHalCapCriterionType& criterionType : capCfg.criterionTypes) { - EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterionType(criterionType)); - EXPECT_TRUE(criterionTypeMap.insert({criterionType.name, criterionType}).second); + EXPECT_TRUE(capCfg.criteriaV2.has_value()); + std::unordered_set criterionTagSet; + std::unordered_set forceUseCriterionUseSet; + for (const auto& criterion : capCfg.criteriaV2.value()) { + EXPECT_TRUE(criterion.has_value()); + if (criterion.value().getTag() != AudioHalCapCriterionV2::forceConfigForUse) { + EXPECT_TRUE(criterionTagSet.insert(criterion.value().getTag()).second); + } else { + auto forceUseCriterion = + criterion.value().get(); + EXPECT_TRUE(forceUseCriterionUseSet.insert(forceUseCriterion.forceUse).second); + } + EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion(criterion.value())); } - std::unordered_set criterionNameSet; - for (const AudioHalCapCriterion& criterion : capCfg.criteria) { - EXPECT_TRUE(criterionNameSet.insert(criterion.name).second); - EXPECT_EQ(criterionTypeMap.count(criterion.criterionTypeName), 1UL); - EXPECT_NO_FATAL_FAILURE(ValidateAudioHalCapCriterion( - criterion, criterionTypeMap.at(criterion.criterionTypeName))); - } - EXPECT_EQ(criterionTypeMap.size(), criterionNameSet.size()); + ValidateAudioHalCapDomains(capCfg.domains.value(), capCfg.criteriaV2.value()); } /** diff --git a/audio/policy/1.0/vts/functional/Android.bp b/audio/policy/1.0/vts/functional/Android.bp index b32c223183..c2335e463c 100644 --- a/audio/policy/1.0/vts/functional/Android.bp +++ b/audio/policy/1.0/vts/functional/Android.bp @@ -17,8 +17,9 @@ cc_test { "libxml2", "liblog", "libmedia_helper", - "libaudiopolicyengine_config", + "libaudiopolicycapengine_config", "libaudiopolicycomponents", + "libaudiopolicyengine_config", "libaudiopolicyengineconfigurable_pfwwrapper", "android.hardware.audio.common.test.utility", "libparameter", diff --git a/audio/policy/1.0/xml/api/current.txt b/audio/policy/1.0/xml/api/current.txt index 01d77d7725..19a8123376 100644 --- a/audio/policy/1.0/xml/api/current.txt +++ b/audio/policy/1.0/xml/api/current.txt @@ -162,7 +162,9 @@ package audio.policy.V1_0 { public static class ProductStrategies.ProductStrategy { ctor public ProductStrategies.ProductStrategy(); method public java.util.List getAttributesGroup(); + method public int getId(); method public String getName(); + method public void setId(int); method public void setName(String); } diff --git a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd index 40396bb9b9..02e593a25f 100644 --- a/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd +++ b/audio/policy/1.0/xml/audio_policy_engine_configuration.xsd @@ -105,6 +105,7 @@ +