Add missing Cap Settings aidl support and helper

Bug: 307310023
Test: atest AudioCoreConfig

Change-Id: I08c71ce9a67f065df36f71c0602e2c9e4e97ae6b
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index f5b590b..f51f65e 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -54,6 +54,7 @@
         "AidlConversionXsdc.cpp",
         "AudioPolicyConfigXmlConverter.cpp",
         "Bluetooth.cpp",
+        "CapEngineConfigXmlConverter.cpp",
         "Config.cpp",
         "Configuration.cpp",
         "EngineConfigXmlConverter.cpp",
@@ -83,14 +84,17 @@
         "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 0000000..8210664
--- /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 <aidl/android/media/audio/common/AudioProductStrategyType.h>
+#include <android-base/logging.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <utils/FastStrcmp.h>
+
+#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<std::vector<std::optional<AudioHalCapDomain>>>&
+CapEngineConfigXmlConverter::getAidlCapEngineConfig() {
+    return mAidlCapDomains;
+}
+
+ConversionResult<AudioHalCapRule::CriterionRule> 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<Tag::availableInputDevices>();
+        rule.criterionTypeValue =
+                VALUE_OR_RETURN(convertDeviceTypeToAidl(gLegacyInputDevicePrefix + criterionValue));
+    } else if (iequals(criterionName, toString(Tag::availableOutputDevices))) {
+        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableOutputDevices>();
+        rule.criterionTypeValue = VALUE_OR_RETURN(
+                convertDeviceTypeToAidl(gLegacyOutputDevicePrefix + criterionValue));
+    } else if (iequals(criterionName, toString(Tag::availableInputDevicesAddresses))) {
+        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>();
+        rule.criterionTypeValue =
+                AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(criterionValue);
+    } else if (iequals(criterionName, toString(Tag::availableOutputDevicesAddresses))) {
+        rule.criterion = AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>();
+        rule.criterionTypeValue =
+                AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(criterionValue);
+    } else if (iequals(criterionName, toString(Tag::telephonyMode))) {
+        rule.criterion = AudioHalCapCriterionV2::make<Tag::telephonyMode>();
+        rule.criterionTypeValue = VALUE_OR_RETURN(convertTelephonyModeToAidl(criterionValue));
+    } else if (!fastcmp<strncmp>(criterionName.c_str(), kXsdcForceConfigForUse,
+            strlen(kXsdcForceConfigForUse))) {
+        rule.criterion = AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
+                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<AudioHalCapRule> 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<int> getAudioProductStrategyId(const std::string& path) {
+    std::vector<std::string> 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<AudioSource> getAudioSource(const std::string& path) {
+    std::vector<std::string> 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<AudioStreamType> getAudioStreamType(const std::string& path) {
+    std::vector<std::string> 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<std::string> 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<AudioHalCapParameter> 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<std::vector<AudioHalCapParameter>>
+CapEngineConfigXmlConverter::convertSettingToAidl(
+        const eng_xsd::SettingsType::Configuration& xsdcSetting) {
+    std::vector<AudioHalCapParameter> aidlCapParameterSettings;
+    for (const auto& element : xsdcSetting.getConfigurableElement()) {
+        aidlCapParameterSettings.push_back(VALUE_OR_FATAL(convertParamToAidl(element)));
+    }
+    return aidlCapParameterSettings;
+}
+
+ConversionResult<AudioHalCapConfiguration> 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<eng_xsd::SettingsType::Configuration> getConfigurationByName(
+        const std::string& name, const std::vector<eng_xsd::SettingsType>& 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<std::vector<AudioHalCapConfiguration>>
+CapEngineConfigXmlConverter::convertConfigurationsToAidl(
+        const std::vector<eng_xsd::ConfigurationsType>& xsdcConfigurationsVec,
+        const std::vector<eng_xsd::SettingsType>& xsdcSettingsVec) {
+    if (xsdcConfigurationsVec.empty() || xsdcSettingsVec.empty()) {
+        LOG(ERROR) << __func__ << " empty configurations/settings";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioHalCapConfiguration> 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<AudioHalCapDomain> 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<eng_xsd::ConfigurableDomainType,
+                                                       AudioHalCapDomain>(
+                        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 631cdce..5a8b0a3 100644
--- a/audio/aidl/default/EngineConfigXmlConverter.cpp
+++ b/audio/aidl/default/EngineConfigXmlConverter.cpp
@@ -26,15 +26,19 @@
 #include <aidl/android/media/audio/common/AudioProductStrategyType.h>
 #include <android-base/logging.h>
 
+#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::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 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<int>(AudioProductStrategyType::name)}
 
@@ -74,6 +83,13 @@
     return it->second;
 }
 
+ConversionResult<int> 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 @@
     }
     AudioAttributes aidlAudioAttributes;
     if (xsdcAudioAttributes.hasContentType()) {
-        aidlAudioAttributes.contentType = static_cast<AudioContentType>(
-                xsdcAudioAttributes.getFirstContentType()->getValue());
+        aidlAudioAttributes.contentType = VALUE_OR_FATAL(convertAudioContentTypeToAidl(
+                xsdcAudioAttributes.getFirstContentType()->getValue()));
     }
     if (xsdcAudioAttributes.hasUsage()) {
-        aidlAudioAttributes.usage =
-                static_cast<AudioUsage>(xsdcAudioAttributes.getFirstUsage()->getValue());
+        aidlAudioAttributes.usage = VALUE_OR_FATAL(
+                convertAudioUsageToAidl(xsdcAudioAttributes.getFirstUsage()->getValue()));
     }
     if (xsdcAudioAttributes.hasSource()) {
-        aidlAudioAttributes.source =
-                static_cast<AudioSource>(xsdcAudioAttributes.getFirstSource()->getValue());
+        aidlAudioAttributes.source = VALUE_OR_FATAL(
+                convertAudioSourceToAidl(xsdcAudioAttributes.getFirstSource()->getValue()));
     }
     if (xsdcAudioAttributes.hasFlags()) {
         std::vector<eng_xsd::FlagType> xsdcFlagTypeVec =
                 xsdcAudioAttributes.getFirstFlags()->getValue();
-        for (const eng_xsd::FlagType& xsdcFlagType : xsdcFlagTypeVec) {
-            if (xsdcFlagType != eng_xsd::FlagType::AUDIO_FLAG_NONE) {
-                aidlAudioAttributes.flags |= 1 << (static_cast<int>(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<int>{-1};
@@ -131,8 +144,10 @@
     static const int kStreamTypeEnumOffset =
             static_cast<int>(eng_xsd::Stream::AUDIO_STREAM_VOICE_CALL) -
             static_cast<int>(AudioStreamType::VOICE_CALL);
-    aidlAttributesGroup.streamType = static_cast<AudioStreamType>(
-            static_cast<int>(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 @@
     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 @@
     }
     if (getXsdcConfig()->hasCriteria() && getXsdcConfig()->hasCriterion_types()) {
         AudioHalEngineConfig::CapSpecificConfig capSpecificConfig;
-        capSpecificConfig.criteria = VALUE_OR_FATAL(
-                (convertWrappedCollectionToAidl<eng_xsd::CriteriaType, eng_xsd::CriterionType,
-                                                AudioHalCapCriterion>(
-                        getXsdcConfig()->getCriteria(), &eng_xsd::CriteriaType::getCriterion,
-                        &convertCapCriterionToAidl)));
-        capSpecificConfig.criterionTypes =
-                VALUE_OR_FATAL((convertWrappedCollectionToAidl<eng_xsd::CriterionTypesType,
-                                                               eng_xsd::CriterionTypeType,
-                                                               AudioHalCapCriterionType>(
-                        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 1720949..ba6110d 100644
--- a/audio/aidl/default/XsdcConversion.cpp
+++ b/audio/aidl/default/XsdcConversion.cpp
@@ -10,11 +10,21 @@
 #include <aidl/android/media/audio/common/AudioPortConfig.h>
 #include <media/AidlConversionCppNdk.h>
 #include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <utils/FastStrcmp.h>
+
+#include <Utils.h>
 
 #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::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<std::string> assertNonEmpty(const std::string& s) {
     if (s.empty()) {
         LOG(ERROR) << __func__ << " Review Audio Policy config: "
@@ -51,6 +78,100 @@
 
 #define NON_EMPTY_STRING_OR_FATAL(s) VALUE_OR_FATAL(assertNonEmpty(s))
 
+ConversionResult<int32_t> convertAudioFlagsToAidl(
+        const std::vector<eng_xsd::FlagType>& 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<int>(legacyFlag);
+        }
+    }
+    ConversionResult<int32_t> result = legacy2aidl_audio_flags_mask_t_int32_t_mask(
+            static_cast<audio_flags_mask_t>(legacyFlagMask));
+    if (!result.ok()) {
+        LOG(ERROR) << __func__ << " Review Audio Policy config, " << legacyFlagMask
+                   << " has invalid flag(s).";
+        return unexpected(BAD_VALUE);
+    }
+    return result;
+}
+
+ConversionResult<AudioStreamType> 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<AudioStreamType> 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<AudioSource> 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<AudioSource> 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<AudioContentType> 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<AudioContentType> 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<AudioUsage> 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<AudioUsage> 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<AudioFormatDescription> convertAudioFormatToAidl(const std::string& xsdcFormat) {
     audio_format_t legacyFormat = ::android::formatFromString(xsdcFormat, AUDIO_FORMAT_DEFAULT);
     ConversionResult<AudioFormatDescription> result =
@@ -410,32 +531,240 @@
     return result;
 }
 
+ConversionResult<AudioPolicyForcedConfig> 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<AudioMode> 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<AudioDeviceAddress> convertDeviceAddressToAidl(const std::string& xsdcAddress) {
+    return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(xsdcAddress);
+}
+
+ConversionResult<eng_xsd::CriterionTypeType> getCriterionTypeByName(
+        const std::string& name,
+        const std::vector<eng_xsd::CriterionTypesType>& 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<std::vector<std::optional<AudioHalCapCriterionV2>>>
+convertCapCriteriaCollectionToAidl(
+        const std::vector<eng_xsd::CriteriaType>& xsdcCriteriaVec,
+        const std::vector<eng_xsd::CriterionTypesType>& xsdcCriterionTypesVec) {
+    std::vector<std::optional<AudioHalCapCriterionV2>> 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<AudioHalCapCriterionV2>(VALUE_OR_FATAL(
+                            convertCapCriterionV2ToAidl(xsdcCriterion, xsdcCriterionTypesVec))));
+        }
+    }
+    return resultAidlCriterionVec;
+}
+
+ConversionResult<std::vector<AudioDeviceDescription>> convertDevicesToAidl(
+        const eng_xsd::CriterionTypeType& xsdcDeviceCriterionType) {
+    if (xsdcDeviceCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioDeviceDescription> 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<audio_devices_t>(integerValue))));
+        }
+    }
+    return aidlDevices;
+}
+
+ConversionResult<std::vector<AudioDeviceAddress>> convertDeviceAddressesToAidl(
+        const eng_xsd::CriterionTypeType& xsdcDeviceAddressesCriterionType) {
+    if (xsdcDeviceAddressesCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioDeviceAddress> 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<AudioDeviceAddress::Tag::id>(xsdcValue.getLiteral()));
+        }
+    }
+    return aidlDeviceAddresses;
+}
+
+ConversionResult<std::vector<AudioMode>> convertTelephonyModesToAidl(
+        const eng_xsd::CriterionTypeType& xsdcTelephonyModeCriterionType) {
+    if (xsdcTelephonyModeCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioMode> 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<std::vector<AudioPolicyForcedConfig>> convertForcedConfigsToAidl(
+        const eng_xsd::CriterionTypeType& xsdcForcedConfigCriterionType) {
+    if (xsdcForcedConfigCriterionType.getValues().empty()) {
+        LOG(ERROR) << __func__ << " no values provided";
+        return unexpected(BAD_VALUE);
+    }
+    std::vector<AudioPolicyForcedConfig> 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<AudioPolicyForceUse> convertForceUseCriterionToAidl(
+        const std::string& xsdcCriterionName) {
+    if (!fastcmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForCommunication,
+            strlen(kXsdcForceConfigForCommunication))) {
+        return AudioPolicyForceUse::COMMUNICATION;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForMedia,
+            strlen(kXsdcForceConfigForMedia))) {
+        return AudioPolicyForceUse::MEDIA;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForRecord,
+            strlen(kXsdcForceConfigForRecord))) {
+        return AudioPolicyForceUse::RECORD;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForDock,
+            strlen(kXsdcForceConfigForDock))) {
+        return AudioPolicyForceUse::DOCK;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForSystem,
+            strlen(kXsdcForceConfigForSystem))) {
+        return AudioPolicyForceUse::SYSTEM;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForHdmiSystemAudio,
+            strlen(kXsdcForceConfigForHdmiSystemAudio))) {
+        return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForEncodedSurround,
+            strlen(kXsdcForceConfigForEncodedSurround))) {
+        return AudioPolicyForceUse::ENCODED_SURROUND;
+    }
+    if (!fasticmp<strncmp>(xsdcCriterionName.c_str(), kXsdcForceConfigForVibrateRinging,
+            strlen(kXsdcForceConfigForVibrateRinging))) {
+        return AudioPolicyForceUse::VIBRATE_RINGING;
+    }
+    LOG(ERROR) << __func__ << " unrecognized force use " << xsdcCriterionName;
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
+        const eng_xsd::CriterionType& xsdcCriterion,
+        const std::vector<eng_xsd::CriterionTypesType>& 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<Tag::availableInputDevices>(
+                VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevices))) {
+        return AudioHalCapCriterionV2::make<Tag::availableOutputDevices>(
+                VALUE_OR_RETURN(convertDevicesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableInputDevicesAddresses))) {
+        return AudioHalCapCriterionV2::make<Tag::availableInputDevicesAddresses>(
+                VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::availableOutputDevicesAddresses))) {
+        return AudioHalCapCriterionV2::make<Tag::availableOutputDevicesAddresses>(
+                VALUE_OR_RETURN(convertDeviceAddressesToAidl(xsdcCriterionType)));
+    }
+    if (iequals(xsdcCriterion.getName(), toString(Tag::telephonyMode))) {
+        return AudioHalCapCriterionV2::make<Tag::telephonyMode>(
+                VALUE_OR_RETURN(convertTelephonyModesToAidl(xsdcCriterionType)));
+    }
+    if (!fastcmp<strncmp>(xsdcCriterion.getName().c_str(), kXsdcForceConfigForUse,
+            strlen(kXsdcForceConfigForUse))) {
+        return AudioHalCapCriterionV2::make<Tag::forceConfigForUse>(
+                VALUE_OR_RETURN(convertForceUseCriterionToAidl(xsdcCriterion.getName())),
+                VALUE_OR_RETURN(convertForcedConfigsToAidl(xsdcCriterionType)));
+    }
+    LOG(ERROR) << __func__ << " unrecognized criterion " << xsdcCriterion.getName();
+    return unexpected(BAD_VALUE);
+}
+
 ConversionResult<AudioHalCapCriterion> 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<std::string> convertCriterionTypeValueToAidl(
-        const eng_xsd::ValueType& xsdcCriterionTypeValue) {
-    return xsdcCriterionTypeValue.getLiteral();
-}
-
-ConversionResult<AudioHalCapCriterionType> convertCapCriterionTypeToAidl(
-        const eng_xsd::CriterionTypeType& xsdcCriterionType) {
-    AudioHalCapCriterionType aidlCapCriterionType;
-    aidlCapCriterionType.name = xsdcCriterionType.getName();
-    aidlCapCriterionType.isInclusive = !(static_cast<bool>(xsdcCriterionType.getType()));
-    aidlCapCriterionType.values = VALUE_OR_RETURN(
-            (convertWrappedCollectionToAidl<eng_xsd::ValuesType, eng_xsd::ValueType, std::string>(
-                    xsdcCriterionType.getValues(), &eng_xsd::ValuesType::getValue,
-                    &convertCriterionTypeValueToAidl)));
-    return aidlCapCriterionType;
-}
-
 ConversionResult<AudioHalVolumeCurve::CurvePoint> 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 0000000..cb99923
--- /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 0000000..4e7c0bb
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/PolicyConfigurableDomains.xsd
@@ -0,0 +1,467 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <!-- BEGIN W3cXmlAttributes.xsd -->
+    <xs:annotation>
+        <xs:documentation>
+            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
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:annotation>
+        <xs:documentation>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:
+            &lt;schema . . .>
+            . . .
+            &lt;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.
+
+            &lt;type . . .>
+            . . .
+            &lt;attributeGroup ref="xml:specialAttrs"/>
+
+            will define a type which will schema-validate an instance
+            element with any of those attributes</xs:documentation>
+    </xs:annotation>
+
+    <xs:annotation>
+        <xs:documentation>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.
+        </xs:documentation>
+    </xs:annotation>
+
+    <xs:attribute name="lang">
+        <xs:annotation>
+            <xs:documentation>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.</xs:documentation>
+        </xs:annotation>
+        <xs:simpleType>
+            <xs:union memberTypes="xs:language">
+                <xs:simpleType name="langEnum">
+                    <xs:restriction base="xs:string">
+                        <xs:enumeration value=""/>
+                    </xs:restriction>
+                </xs:simpleType>
+            </xs:union>
+        </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="space">
+        <xs:simpleType name="spaceEnum">
+            <xs:restriction base="xs:NCName">
+                <xs:enumeration value="default"/>
+                <xs:enumeration value="preserve"/>
+            </xs:restriction>
+        </xs:simpleType>
+    </xs:attribute>
+
+    <xs:attribute name="base" type="xs:anyURI">
+        <xs:annotation>
+            <xs:documentation>See http://www.w3.org/TR/xmlbase/ for
+                information about this attribute.</xs:documentation>
+        </xs:annotation>
+    </xs:attribute>
+
+    <xs:attribute name="id" type="xs:ID">
+        <xs:annotation>
+            <xs:documentation>See http://www.w3.org/TR/xml-id/ for
+                information about this attribute.</xs:documentation>
+        </xs:annotation>
+    </xs:attribute>
+
+    <xs:attributeGroup name="specialAttrs">
+        <xs:attribute ref="xml:base"/>
+        <xs:attribute ref="xml:lang"/>
+        <xs:attribute ref="xml:space"/>
+    </xs:attributeGroup>
+    <!-- END W3cXmlAttributes.xsd -->
+
+    <!-- BEGIN ParameterSettings.xsd -->
+    <!-- BUG b/147297854 - removed "abstract" from type definition -->
+    <xs:complexType name="BooleanParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:restriction base="xs:string">
+                <xs:pattern value="([01][\s]*)+"/>
+                <xs:pattern value="((0x0|0x1)[\s]*)+"/>
+                <xs:attribute name="Name" type="xs:string" use="required"/>
+            </xs:restriction-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="IntegerParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:restriction base="xs:string">
+                <xs:pattern value="(0|([+-]?[1-9][0-9]*))(\s+(0|([+-]?[1-9][0-9]*)))*"/>
+                <xs:pattern value="(0x[0-9a-fA-F]+)(\s+(0x[0-9a-fA-F]+))*"/>
+                <xs:attribute name="Name" type="xs:string" use="required"/>
+            </xs:restriction-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="EnumParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:extension base="xs:string">
+                <xs:attribute name="Name" type="xs:string" use="required"/>
+            </xs:extension-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="PointParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+            <!--xs:restriction base="xs:string">
+                <xs:pattern value="((0|[+-]?0\.[0-9]+|(([+-]?[1-9][0-9]*)(\.[0-9]+)?))([Ee][+-]?[0-9]+)?)(\s+(0|[+-]?0\.[0-9]+|(([+-]?[1-9][0-9]*)(\.[0-9]+)?))([Ee][+-]?[0-9]+)?)*"/>
+                <xs:pattern value="(0x[0-9a-fA-F]+)(\s+(0x[0-9a-fA-F]+))*"/>
+                <xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
+            </xs:restriction-->
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:complexType name="BitParameterBlockType">
+        <xs:sequence>
+            <xs:element name="BitParameter" maxOccurs="unbounded" type="IntegerParameterType"/>
+        </xs:sequence>
+        <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="StringParameterType">
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="Name" type="ParameterNameEnumType" use="required"/>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+    <xs:group name="ParameterBlockGroup">
+        <xs:choice>
+            <xs:element name="BooleanParameter" type="BooleanParameterType"/>
+            <xs:element name="IntegerParameter" type="IntegerParameterType"/>
+            <xs:element name="EnumParameter" type="EnumParameterType"/>
+            <xs:element name="FixedPointParameter" type="PointParameterType"/>
+            <xs:element name="FloatingPointParameter" type="PointParameterType"/>
+            <xs:element name="BitParameterBlock" type="BitParameterBlockType">
+                <xs:unique name="BitParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+            <xs:element name="StringParameter" type="StringParameterType"/>
+            <!--xs:element name="Component" type="ParameterBlockType"/-->
+            <xs:element name="ParameterBlock" type="ParameterBlockType">
+                <xs:unique name="ParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:choice>
+    </xs:group>
+    <xs:complexType name="ParameterBlockType">
+        <xs:sequence>
+            <xs:group ref="ParameterBlockGroup" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="Name" type="xs:NMTOKEN" use="required"/>
+    </xs:complexType>
+    <!-- END ParameterSettings.xsd -->
+
+    <!-- BEGIN ConfigurableDomain.xsd -->
+    <xs:complexType name="SelectionCriterionRuleType">
+        <xs:attribute name="SelectionCriterion" type="xs:NMTOKEN" use="required"/>
+        <xs:attribute name="MatchesWhen" use="required">
+            <xs:simpleType name="MatchesWhenEnum">
+                <xs:restriction base="xs:NMTOKEN">
+                    <xs:enumeration value="Is"/>
+                    <xs:enumeration value="IsNot"/>
+                    <xs:enumeration value="Includes"/>
+                    <xs:enumeration value="Excludes"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="Value" use="required" type="xs:NMTOKEN"/>
+    </xs:complexType>
+    <xs:group name="RuleGroup">
+        <xs:choice>
+            <xs:element name="CompoundRule" type="CompoundRuleType"/>
+            <xs:element name="SelectionCriterionRule" type="SelectionCriterionRuleType"/>
+        </xs:choice>
+    </xs:group>
+    <xs:complexType name="CompoundRuleType">
+        <xs:sequence>
+            <xs:group ref="RuleGroup" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="Type">
+            <xs:simpleType name="TypeEnum">
+                <xs:restriction base="xs:NMTOKEN">
+                    <xs:enumeration value="Any"/>
+                    <xs:enumeration value="All"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="ConfigurationsType">
+        <xs:sequence>
+            <xs:element maxOccurs="unbounded" name="Configuration">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="CompoundRule" type="CompoundRuleType" minOccurs="0" maxOccurs="1"/>
+                    </xs:sequence>
+                    <xs:attribute name="Name" use="required" type="xs:NCName"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:group name="ComponentGroup">
+        <xs:sequence>
+            <xs:group ref="ParameterBlockGroup"/>
+        </xs:sequence>
+    </xs:group>
+    <xs:complexType name="ComponentType">
+        <xs:sequence>
+            <xs:choice>
+                <xs:group ref="ComponentGroup" maxOccurs="unbounded"/>
+                <xs:element name="Subsystem" type="ComponentType" maxOccurs="unbounded"/>
+            </xs:choice>
+        </xs:sequence>
+        <xs:attribute name="Name" use="required" type="xs:NCName"/>
+    </xs:complexType>
+    <xs:complexType name="ConfigurableElementsType">
+        <xs:sequence>
+            <xs:element maxOccurs="unbounded" minOccurs="0" name="ConfigurableElement">
+                <xs:complexType>
+                    <xs:attribute name="Path" use="required">
+                        <xs:simpleType>
+                            <xs:restriction base="xs:anyURI">
+                                <xs:pattern value="/.*[^/]"/>
+                            </xs:restriction>
+                        </xs:simpleType>
+                    </xs:attribute>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="ConfigurableElementSettingsType">
+        <xs:choice>
+            <xs:element name="BooleanParameter" type="BooleanParameterType"/>
+            <xs:element name="IntegerParameter" type="IntegerParameterType"/>
+            <xs:element name="EnumParameter" type="EnumParameterType"/>
+            <xs:element name="FixedPointParameter" type="PointParameterType"/>
+            <xs:element name="FloatingPointParameter" type="PointParameterType"/>
+            <xs:element name="BitParameter" type="IntegerParameterType"/>
+            <xs:element name="BitParameterBlock" type="BitParameterBlockType">
+                <xs:unique name="BitParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+            <xs:element name="StringParameter" type="StringParameterType"/>
+            <!--xs:element name="Component" type="ParameterBlockType"/-->
+            <xs:element name="ParameterBlock" type="ParameterBlockType">
+                <xs:unique name="ParameterBlockSubElementsUniqueness">
+                    <xs:selector xpath="*"/>
+                    <xs:field xpath="@Name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:choice>
+        <!--xs:choice>
+            <xs:element name="BitParameter" type="IntegerParameterType"/>
+            <xs:group ref="ComponentGroup"/>
+        </xs:choice-->
+        <xs:attribute name="Path" use="required">
+            <xs:simpleType>
+                <xs:restriction base="xs:anyURI">
+                    <xs:pattern value="/.*[^/]"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="SettingsType">
+        <xs:sequence>
+            <xs:element maxOccurs="unbounded" minOccurs="0" name="Configuration">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="ConfigurableElement" minOccurs="0" maxOccurs="unbounded" type="ConfigurableElementSettingsType"/>
+                    </xs:sequence>
+                    <xs:attribute name="Name" use="required" type="xs:NCName"/>
+                </xs:complexType>
+                <xs:unique name="ConfigurableElementUniqueness">
+                    <xs:selector xpath="ConfigurableElement"/>
+                    <xs:field xpath="@Path"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="ConfigurableDomainType">
+        <xs:sequence>
+            <xs:element name="Configurations" type="ConfigurationsType"/>
+            <xs:element name="ConfigurableElements" type="ConfigurableElementsType"/>
+            <xs:element name="Settings" type="SettingsType" minOccurs="0"/>
+        </xs:sequence>
+        <xs:attribute name="Name" use="required" type="xs:NCName"/>
+        <xs:attribute name="SequenceAware" use="optional" type="xs:boolean" default="false"/>
+    </xs:complexType>
+    <xs:element name="ConfigurableDomain" type="ConfigurableDomainType"/>
+    <!-- END ConfigurableDomain.xsd -->
+
+    <!-- BEGIN ConfigurableDomains.xsd -->
+    <xs:element name="ConfigurableDomains">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="unbounded" name="ConfigurableDomain" type="ConfigurableDomainType">
+                    <xs:key name="ConfigurableElementKey">
+                        <xs:selector xpath="ConfigurableElements/ConfigurableElement"/>
+                        <xs:field xpath="@Path"/>
+                    </xs:key>
+                    <xs:keyref refer="ConfigurableElementKey" name="ConfigurableDomainReference">
+                        <xs:selector xpath="Settings/Configuration/ConfigurableElement"/>
+                        <xs:field xpath="@Path"/>
+                    </xs:keyref>
+                    <xs:key name="ConfigurationKey">
+                        <xs:selector xpath="Configurations/Configuration"/>
+                        <xs:field xpath="@Name"/>
+                    </xs:key>
+                    <xs:keyref refer="ConfigurationKey" name="ConfigurationReference2">
+                        <xs:selector xpath="ConfigurableElements/ConfigurableElement/Configuration"/>
+                        <xs:field xpath="@Name"/>
+                    </xs:keyref>
+                    <xs:keyref refer="ConfigurationKey" name="ConfigurationReference">
+                        <xs:selector xpath="Settings/Configuration"/>
+                        <xs:field xpath="@Name"/>
+                    </xs:keyref>
+                </xs:element>
+            </xs:sequence>
+            <xs:attribute name="SystemClassName" use="required" type="xs:NCName"/>
+        </xs:complexType>
+        <xs:unique name="ConfigurableDomainUniqueness">
+            <xs:selector xpath="ConfigurableDomain"/>
+            <xs:field xpath="@Name"/>
+        </xs:unique>
+    </xs:element>
+    <!-- END ConfigurableDomains.xsd -->
+
+    <xs:simpleType name="ParameterNameEnumType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="volume_profile"/>
+
+            <xs:enumeration value="communication"/>
+            <xs:enumeration value="ambient"/>
+            <xs:enumeration value="builtin_mic"/>
+            <xs:enumeration value="bluetooth_sco_headset"/>
+            <xs:enumeration value="wired_headset"/>
+            <xs:enumeration value="hdmi"/>
+            <xs:enumeration value="telephony_rx"/>
+            <xs:enumeration value="back_mic"/>
+            <xs:enumeration value="remote_submix"/>
+            <xs:enumeration value="anlg_dock_headset"/>
+            <xs:enumeration value="dgtl_dock_headset"/>
+            <xs:enumeration value="usb_accessory"/>
+            <xs:enumeration value="usb_device"/>
+            <xs:enumeration value="fm_tuner"/>
+            <xs:enumeration value="tv_tuner"/>
+            <xs:enumeration value="line"/>
+            <xs:enumeration value="spdif"/>
+            <xs:enumeration value="bluetooth_a2dp" />
+            <xs:enumeration value="loopback" />
+            <xs:enumeration value="ip" />
+            <xs:enumeration value="bus" />
+            <xs:enumeration value="proxy"/>
+            <xs:enumeration value="usb_headset"/>
+            <xs:enumeration value="bluetooth_ble"/>
+            <xs:enumeration value="hdmi_arc"/>
+            <xs:enumeration value="echo_reference"/>
+            <xs:enumeration value="ble_headset"/>
+            <xs:enumeration value="stub"/>
+            <xs:enumeration value="hdmi_earc"/>
+
+            <xs:enumeration value="device_address"/>
+
+            <xs:enumeration value="earpiece" />
+            <xs:enumeration value="speaker" />
+            <xs:enumeration value="wired_headphone" />
+            <xs:enumeration value="bluetooth_sco" />
+            <xs:enumeration value="bluetooth_sco_carkit"/>
+            <xs:enumeration value="bluetooth_a2dp_headphones"/>
+            <xs:enumeration value="bluetooth_a2dp_speaker"/>
+            <xs:enumeration value="telephony_tx"/>
+            <xs:enumeration value="fm"/>
+            <xs:enumeration value="aux_line"/>
+            <xs:enumeration value="speaker_safe"/>
+            <xs:enumeration value="hearing_aid" />
+            <xs:enumeration value="echo_canceller" />
+            <xs:enumeration value="ble_speaker" />
+            <xs:enumeration value="ble_broadcast" />
+        </xs:restriction>
+    </xs:simpleType>
+</xs:schema>
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 0000000..481abbf
--- /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<android.audio.policy.capengine.configuration.IntegerParameterType> 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<android.audio.policy.capengine.configuration.ComponentType> 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<android.audio.policy.capengine.configuration.ConfigurableDomainType> 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<android.audio.policy.capengine.configuration.ConfigurableElementsType.ConfigurableElement> 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<android.audio.policy.capengine.configuration.ConfigurationsType.Configuration> 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<android.audio.policy.capengine.configuration.SettingsType.Configuration> getConfiguration();
+  }
+
+  public static class SettingsType.Configuration {
+    ctor public SettingsType.Configuration();
+    method @Nullable public java.util.List<android.audio.policy.capengine.configuration.ConfigurableElementSettingsType> 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 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/api/last_current.txt
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 0000000..e69de29
--- /dev/null
+++ b/audio/aidl/default/config/audioPolicy/capengine/api/last_removed.txt
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 0000000..d802177
--- /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 063b05d..8e0e9a2 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 @@
   public static class ProductStrategies.ProductStrategy {
     ctor public ProductStrategies.ProductStrategy();
     method @Nullable public java.util.List<android.audio.policy.engine.configuration.AttributesGroup> 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 40396bb..e2508ea 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 @@
                         <xs:element name="AttributesGroup" type="AttributesGroup" minOccurs="1" maxOccurs="unbounded"/>
                     </xs:sequence>
                     <xs:attribute name="name" type="xs:string" use="required"/>
+                    <xs:attribute name="id" type="xs:int" use="required"/>
                 </xs:complexType>
             </xs:element>
         </xs:sequence>
@@ -188,6 +189,19 @@
         </xs:sequence>
     </xs:complexType>
     <xs:complexType name="valueType">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                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.
+            </xs:documentation>
+        </xs:annotation>
         <xs:attribute name="literal" type="xs:string" use="required"/>
         <xs:attribute name="numerical" type="xs:long" use="required"/>
         <xs:attribute name="android_type" type="longDecimalOrHexType" use="optional"/>
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 0000000..e5da4f4
--- /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 <aidl/android/hardware/audio/core/BnConfig.h>
+#include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio_config.h>
+
+#include <android_audio_policy_capengine_configuration.h>
+#include <android_audio_policy_capengine_configuration_enums.h>
+
+#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<std::optional<::aidl::android::media::audio::common::AudioHalCapDomain>>>&
+    getAidlCapEngineConfig();
+
+  private:
+    ConversionResult<std::vector<aidlcommon::AudioHalCapParameter>> convertSettingToAidl(
+            const capconfiguration::SettingsType::Configuration& xsdcSetting);
+
+    ConversionResult<std::vector<aidlcommon::AudioHalCapConfiguration>> convertConfigurationsToAidl(
+            const std::vector<capconfiguration::ConfigurationsType>& xsdcConfigurationsVec,
+            const std::vector<capconfiguration::SettingsType>& xsdcSettingsVec);
+
+    ConversionResult<aidlcommon::AudioHalCapConfiguration> convertConfigurationToAidl(
+            const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration,
+            const capconfiguration::SettingsType::Configuration& xsdcSettingConfiguration);
+
+    ConversionResult<aidlcommon::AudioHalCapParameter> convertParamToAidl(
+            const capconfiguration::ConfigurableElementSettingsType& element);
+
+    ConversionResult<aidlcommon::AudioHalCapConfiguration> convertConfigurationToAidl(
+            const capconfiguration::ConfigurationsType::Configuration& xsdcConfiguration);
+    ConversionResult<aidlcommon::AudioHalCapDomain> convertConfigurableDomainToAidl(
+            const capconfiguration::ConfigurableDomainType& xsdcConfigurableDomain);
+
+    const std::optional<capconfiguration::ConfigurableDomains>& getXsdcConfig() {
+        return mConverter.getXsdcConfig();
+    }
+    void init();
+
+    std::optional<std::vector<std::optional<aidlcommon::AudioHalCapDomain>>> mAidlCapDomains;
+    XmlConverter<capconfiguration::ConfigurableDomains> 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 22ac8cb..211c16f 100644
--- a/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
+++ b/audio/aidl/default/include/core-impl/EngineConfigXmlConverter.h
@@ -59,6 +59,7 @@
     ConversionResult<::aidl::android::media::audio::common::AudioHalProductStrategy>
     convertProductStrategyToAidl(const ::android::audio::policy::engine::configuration::
                                          ProductStrategies::ProductStrategy& xsdcProductStrategy);
+    ConversionResult<int> convertProductStrategyIdToAidl(int xsdcId);
     ConversionResult<int> 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 68e6b8e..4b99d72 100644
--- a/audio/aidl/default/include/core-impl/XmlConverter.h
+++ b/audio/aidl/default/include/core-impl/XmlConverter.h
@@ -106,6 +106,19 @@
 }
 
 template <typename X, typename A>
+static ConversionResult<std::vector<std::optional<A>>> convertCollectionToAidlOptionalValues(
+        const std::vector<X>& xsdcTypeVec,
+        std::function<ConversionResult<A>(const X&)> convertToAidl) {
+    std::vector<std::optional<A>> resultAidlTypeVec;
+    resultAidlTypeVec.reserve(xsdcTypeVec.size());
+    for (const X& xsdcType : xsdcTypeVec) {
+        resultAidlTypeVec.push_back(
+                std::optional<A>(std::move(VALUE_OR_FATAL(convertToAidl(xsdcType)))));
+    }
+    return resultAidlTypeVec;
+}
+
+template <typename X, typename A>
 static ConversionResult<std::vector<A>> convertCollectionToAidl(
         const std::vector<X>& xsdcTypeVec,
         std::function<ConversionResult<A>(const X&)> convertToAidl) {
diff --git a/audio/aidl/default/include/core-impl/XsdcConversion.h b/audio/aidl/default/include/core-impl/XsdcConversion.h
index 30dc8b6..e855a3e 100644
--- a/audio/aidl/default/include/core-impl/XsdcConversion.h
+++ b/audio/aidl/default/include/core-impl/XsdcConversion.h
@@ -4,6 +4,7 @@
 
 #include <aidl/android/media/audio/common/AudioHalCapCriterion.h>
 #include <aidl/android/media/audio/common/AudioHalCapCriterionType.h>
+#include <aidl/android/media/audio/common/AudioHalCapCriterionV2.h>
 #include <aidl/android/media/audio/common/AudioHalVolumeCurve.h>
 #include <aidl/android/media/audio/common/AudioPort.h>
 #include <android_audio_policy_configuration.h>
@@ -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<aidlaudiocommon::AudioPolicyForceUse> convertForceUseCriterionToAidl(
+        const std::string& xsdcCriterionName);
+ConversionResult<aidlaudiocommon::AudioPolicyForcedConfig> convertForcedConfigToAidl(
+        const std::string& xsdcForcedConfigCriterionType);
+ConversionResult<aidlaudiocommon::AudioDeviceAddress> convertDeviceAddressToAidl(
+        const std::string& xsdcAddress);
+ConversionResult<aidlaudiocommon::AudioMode> convertTelephonyModeToAidl(
+        const std::string& xsdcModeCriterionType);
+ConversionResult<aidlaudiocommon::AudioDeviceDescription> convertDeviceTypeToAidl(
+        const std::string& xType);
+ConversionResult<std::vector<std::optional<aidlaudiocommon::AudioHalCapCriterionV2>>>
+convertCapCriteriaCollectionToAidl(
+        const std::vector<engineconfiguration::CriteriaType>& xsdcCriteriaVec,
+        const std::vector<engineconfiguration::CriterionTypesType>& xsdcCriterionTypesVec);
+ConversionResult<aidlaudiocommon::AudioHalCapCriterionV2> convertCapCriterionV2ToAidl(
+        const engineconfiguration::CriterionType& xsdcCriterion,
+        const std::vector<engineconfiguration::CriterionTypesType>& xsdcCriterionTypesVec);
+ConversionResult<aidlaudiocommon::AudioHalVolumeCurve::CurvePoint> convertCurvePointToAidl(
+        const std::string& xsdcCurvePoint);
 ConversionResult<std::unique_ptr<Module::Configuration>> convertModuleConfigToAidl(
         const ::android::audio::policy::configuration::Modules::Module& moduleConfig);
+ConversionResult<aidlaudiocommon::AudioUsage> convertAudioUsageToAidl(
+        const engineconfiguration::UsageEnumType& xsdcUsage);
+ConversionResult<aidlaudiocommon::AudioContentType> convertAudioContentTypeToAidl(
+        const engineconfiguration::ContentType& xsdcContentType);
+ConversionResult<aidlaudiocommon::AudioSource> convertAudioSourceToAidl(
+        const engineconfiguration::SourceEnumType& xsdcSourceType);
+ConversionResult<aidlaudiocommon::AudioStreamType> convertAudioStreamTypeToAidl(
+        const engineconfiguration::Stream& xsdStreamType);
+ConversionResult<int32_t> convertAudioFlagsToAidl(
+        const std::vector<engineconfiguration::FlagType>& xsdcFlagTypeVec);
 }  // namespace aidl::android::hardware::audio::core::internal