Configurable Audio Policy: migrate settings to AudioAIDL

Add the missing support of Cap Settings through Audio AIDL.

Bug: 307310023
Test: manual

Change-Id: I06920b3318bffd210829f45f28175df12dc0267f
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index cf594c6..01c9660 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -25,6 +25,25 @@
 
 using StreamTypeVector = std::vector<audio_stream_type_t>;
 
+/**
+ * Legacy audio policy product strategies IDs. These strategies are supported by the default
+ * policy engine.
+ */
+enum legacy_strategy {
+    STRATEGY_NONE = -1,
+    STRATEGY_MEDIA,
+    STRATEGY_PHONE,
+    STRATEGY_SONIFICATION,
+    STRATEGY_SONIFICATION_RESPECTFUL,
+    STRATEGY_DTMF,
+    STRATEGY_ENFORCED_AUDIBLE,
+    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
+    STRATEGY_ACCESSIBILITY,
+    STRATEGY_REROUTING,
+    STRATEGY_CALL_ASSISTANT,
+    STRATEGY_PATCH,
+};
+
 static const audio_attributes_t defaultAttr = AUDIO_ATTRIBUTES_INITIALIZER;
 
 } // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 1f6002f..794c7c0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -49,6 +49,7 @@
     static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
     // The suffix of the "engine default" implementation shared library name.
     static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+    static const constexpr char* const kCapEngineLibraryNameSuffix = "configurable";
 
     // Creates the default (fallback) configuration.
     static sp<const AudioPolicyConfig> createDefault();
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 4edd11f..abeaaf8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -269,6 +269,9 @@
     mSurroundFormats = VALUE_OR_RETURN_STATUS(
             aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
     mSource = kAidlConfigSource;
+    if (aidl.engineConfig.capSpecificConfig.has_value()) {
+        setEngineLibraryNameSuffix(kCapEngineLibraryNameSuffix);
+    }
     // No need to augmentData() as AIDL HAL must provide correct mic addresses.
     return NO_ERROR;
 }
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index d8aac37..7daa064 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -64,5 +64,6 @@
     ],
     defaults: [
         "aconfig_lib_cc_static_link.defaults",
+        "latest_android_media_audio_common_types_cpp_static",
     ],
 }
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index b9c94a4..edb2e29 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -129,6 +129,8 @@
 
     product_strategy_t getProductStrategyByName(const std::string &name) const;
 
+    std::string getProductStrategyName(product_strategy_t id) const;
+
     AudioPolicyManagerObserver *getApmObserver() const { return mApmObserver; }
 
     inline bool isInCall() const
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 1593be0..8162720 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -46,7 +46,7 @@
     using VolumeGroupAttributesVector = std::vector<VolumeGroupAttributes>;
 
 public:
-    ProductStrategy(const std::string &name);
+    ProductStrategy(const std::string &name, int id = PRODUCT_STRATEGY_NONE);
 
     void addAttributes(const VolumeGroupAttributes &volumeGroupAttributes);
 
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index e259e6e..976791f 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -116,6 +116,15 @@
     return PRODUCT_STRATEGY_NONE;
 }
 
+std::string EngineBase::getProductStrategyName(product_strategy_t id) const {
+    for (const auto &iter : mProductStrategies) {
+        if (iter.second->getId() == id) {
+            return iter.second->getName();
+        }
+    }
+    return "";
+}
+
 engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
         const media::audio::common::AudioHalEngineConfig& aidlConfig)
 {
@@ -240,7 +249,7 @@
         loadVolumeConfig(mVolumeGroups, volumeConfig);
     }
     for (auto& strategyConfig : result.parsedConfig->productStrategies) {
-        sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
+        sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name, strategyConfig.id);
         for (const auto &group : strategyConfig.attributesGroups) {
             const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),
                                          [&group](const auto &volumeGroup) {
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 548a20d..c4bf64a 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -18,14 +18,17 @@
 
 #include <EngineConfig.h>
 
+#include <media/AudioProductStrategy.h>
+#include <policy.h>
 #include <system/audio.h>
 
 namespace android {
+
 /**
  * @brief AudioProductStrategies hard coded array of strategies to fill new engine API contract.
  */
 const engineConfig::ProductStrategies gOrderedStrategies = {
-    {"STRATEGY_PHONE",
+    {"STRATEGY_PHONE", STRATEGY_PHONE,
      {
          {AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
@@ -37,7 +40,7 @@
          }
      },
     },
-    {"STRATEGY_SONIFICATION",
+    {"STRATEGY_SONIFICATION", STRATEGY_SONIFICATION,
      {
          {AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
@@ -49,7 +52,7 @@
          }
      },
     },
-    {"STRATEGY_ENFORCED_AUDIBLE",
+    {"STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE,
      {
          {AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
@@ -57,7 +60,7 @@
          }
      },
     },
-    {"STRATEGY_ACCESSIBILITY",
+    {"STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY,
      {
          {AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
@@ -65,7 +68,7 @@
          }
      },
     },
-    {"STRATEGY_SONIFICATION_RESPECTFUL",
+    {"STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL,
      {
          {AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
           {
@@ -77,7 +80,7 @@
          }
      },
     },
-    {"STRATEGY_MEDIA",
+    {"STRATEGY_MEDIA", STRATEGY_MEDIA,
      {
          {AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
@@ -103,7 +106,7 @@
          }
      },
     },
-    {"STRATEGY_DTMF",
+    {"STRATEGY_DTMF", STRATEGY_DTMF,
      {
          {AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
           {
@@ -113,7 +116,7 @@
          }
      },
     },
-    {"STRATEGY_CALL_ASSISTANT",
+    {"STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT,
      {
          {AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
@@ -121,7 +124,7 @@
          }
      },
     },
-    {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
+    {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
      {
          {AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
           {
@@ -140,7 +143,7 @@
  * For compatibility reason why apm volume config file, volume group name is the stream type.
  */
 const engineConfig::ProductStrategies gOrderedSystemStrategies = {
-    {"STRATEGY_REROUTING",
+    {"STRATEGY_REROUTING", STRATEGY_REROUTING,
      {
          {AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
@@ -148,7 +151,7 @@
          }
      },
     },
-    {"STRATEGY_PATCH",
+    {"STRATEGY_PATCH", STRATEGY_PATCH,
      {
          {AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 0d25955..8ed7403 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -19,6 +19,7 @@
 
 #include "ProductStrategy.h"
 
+#include <android/media/audio/common/AudioHalProductStrategy.h>
 #include <media/AudioProductStrategy.h>
 #include <media/TypeConverter.h>
 #include <utils/String8.h>
@@ -30,11 +31,20 @@
 
 namespace android {
 
-ProductStrategy::ProductStrategy(const std::string &name) :
+using media::audio::common::AudioHalProductStrategy;
+
+/*
+ * Note on the id: either is provided (legacy strategies have hard coded id, aidl have
+ * own id, enforced to be started from VENDOR_STRATEGY_ID_START.
+ * REROUTING & PATCH system strategies are added.
+ * To prevent from collision, generate from VENDOR_STRATEGY_ID_START when id is not provided.
+ */
+ProductStrategy::ProductStrategy(const std::string &name, int id) :
     mName(name),
-    mId(static_cast<product_strategy_t>(HandleGenerator<uint32_t>::getNextHandle()))
-{
-}
+    mId((static_cast<product_strategy_t>(id) != PRODUCT_STRATEGY_NONE) ?
+            static_cast<product_strategy_t>(id) :
+            static_cast<product_strategy_t>(AudioHalProductStrategy::VENDOR_STRATEGY_ID_START +
+                    HandleGenerator<uint32_t>::getNextHandle())) {}
 
 void ProductStrategy::addAttributes(const VolumeGroupAttributes &volumeGroupAttributes)
 {
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index ab2c134..d771605 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -10,6 +10,9 @@
 
 cc_library {
     name: "libaudiopolicyengine_config",
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
     export_include_dirs: ["include"],
     include_dirs: [
         "external/libxml2/include",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 119dbd6..054bdae 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -71,6 +71,7 @@
 
 struct ProductStrategy {
     std::string name;
+    int id;
     AttributesGroups attributesGroups;
 };
 
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 3f9ae19..714ab78 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -20,7 +20,6 @@
 #include <sstream>
 #include <stdarg.h>
 #include <string>
-#include <string>
 #include <vector>
 #include <unordered_map>
 
@@ -42,6 +41,7 @@
 
 namespace android {
 
+using media::audio::common::AudioStreamType;
 using utilities::convertTo;
 
 namespace engineConfig {
@@ -66,6 +66,9 @@
                             STRATEGY_ENTRY(ACCESSIBILITY)};
 #undef STRATEGY_ENTRY
 
+    if (id >= media::audio::common::AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
+        return std::to_string(id);
+    }
     auto it = productStrategyMap.find(id);
     if (it == productStrategyMap.end()) {
         return base::unexpected(BAD_VALUE);
@@ -76,8 +79,12 @@
 ConversionResult<AttributesGroup> aidl2legacy_AudioHalAttributeGroup_AttributesGroup(
         const media::audio::common::AudioHalAttributesGroup& aidl) {
     AttributesGroup legacy;
-    legacy.stream = VALUE_OR_RETURN(
-            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+    // StreamType may only be set to AudioStreamType.INVALID when using the
+    // Configurable Audio Policy (CAP) engine. An AudioHalAttributesGroup with
+    // AudioStreamType.INVALID is used when the volume group and attributes are
+    // not associated to any AudioStreamType.
+    legacy.stream = ((aidl.streamType == AudioStreamType::INVALID) ? AUDIO_STREAM_DEFAULT :
+            VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType)));
     legacy.volumeGroup = aidl.volumeGroupName;
     legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
                     aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
@@ -87,8 +94,9 @@
 ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
         const media::audio::common::AudioHalProductStrategy& aidl) {
     ProductStrategy legacy;
-    legacy.name = VALUE_OR_RETURN(
-                    aidl2legacy_AudioHalProductStrategy_ProductStrategyType(aidl.id));
+    legacy.name = aidl.name.value_or(VALUE_OR_RETURN(
+                    aidl2legacy_AudioHalProductStrategy_ProductStrategyType(aidl.id)));
+    legacy.id = aidl.id;
     legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
                     aidl.attributesGroups,
                     aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
@@ -148,7 +156,6 @@
                     aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
     return legacy;
 }
-
 }  // namespace
 
 template<typename E, typename C>
@@ -175,6 +182,7 @@
 
     struct Attributes {
         static constexpr const char *name = "name";
+        static constexpr const char *id = "id";
     };
     static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &ps);
 };
@@ -533,13 +541,21 @@
         ALOGE("ProductStrategyTraits No attribute %s found", Attributes::name);
         return BAD_VALUE;
     }
+    int id = PRODUCT_STRATEGY_NONE;
+    std::string idLiteral = getXmlAttribute(child, Attributes::id);
+    if (!idLiteral.empty()) {
+        if (!convertTo(idLiteral, id)) {
+            return BAD_VALUE;
+        }
+        ALOGV("%s: %s, %s = %d", __FUNCTION__, name.c_str(), Attributes::id, id);
+    }
     ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
 
     size_t skipped = 0;
     AttributesGroups attrGroups;
     deserializeCollection<AttributesGroupTraits>(doc, child, attrGroups, skipped);
 
-    strategies.push_back({name, attrGroups});
+    strategies.push_back({name, id, attrGroups});
     return NO_ERROR;
 }
 
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index a0a4bdf..1c98faf 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -36,10 +36,10 @@
         "libbase_headers",
     ],
     static_libs: [
+        "libaudiopolicycapengine_config",
         "libaudiopolicyengine_common",
         "libaudiopolicyengine_config",
         "libaudiopolicyengineconfigurable_pfwwrapper",
-
     ],
     shared_libs: [
         "libaudio_aidl_conversion_common_cpp",
@@ -56,5 +56,13 @@
     ],
     defaults: [
         "aconfig_lib_cc_static_link.defaults",
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+    required: [
+        "CapClass.xml",
+        "CapProductStrategies.xml",
+        "CapSubsystem-CommonTypes.xml",
+        "CapSubsystem.xml",
+        "ParameterFrameworkConfigurationCap.xml",
     ],
 }
diff --git a/services/audiopolicy/engineconfigurable/config/Android.bp b/services/audiopolicy/engineconfigurable/config/Android.bp
index 8dd13e8..95a7cf8 100644
--- a/services/audiopolicy/engineconfigurable/config/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/Android.bp
@@ -38,6 +38,53 @@
 }
 
 filegroup {
+    name: "audio_policy_engine_aidl_criterion_types_template",
+    srcs: ["example/common/audio_policy_engine_criterion_types_aidl.xml.in"],
+}
+
+filegroup {
     name: "audio_policy_engine_criteria",
     srcs: ["example/common/audio_policy_engine_criteria.xml"],
 }
+
+cc_library_headers {
+    name: "libaudiopolicycapengine_config_headers",
+    export_include_dirs: ["include"],
+}
+
+cc_library {
+    name: "libaudiopolicycapengine_config",
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+    export_header_lib_headers: [
+        "libaudiopolicycapengine_config_headers",
+    ],
+    include_dirs: [
+        "external/libxml2/include",
+    ],
+    srcs: [
+        "src/CapEngineConfig.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudiopolicycomponents",
+        "libaudiopolicyengine_config",
+        "libcutils",
+        "liblog",
+        "libmedia_helper",
+        "libutils",
+        "libxml2",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+        "libaudioclient_headers",
+        "libaudiopolicycapengine_config_headers",
+        "libmedia_headers",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in
new file mode 100644
index 0000000..dc2517b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in
@@ -0,0 +1,96 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 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.
+-->
+<criterion_types>
+    <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="OutputDevicesAddressesType" type="inclusive">
+        <values>
+            <!-- legacy remote submix -->
+            <value literal="0" numerical="1"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="InputDevicesAddressesType" type="inclusive">
+        <values>
+            <!-- legacy remote submix -->
+            <value literal="0" numerical="1"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="AndroidModeType" type="exclusive"/>
+    <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="SPEAKER" numerical="1"/>
+            <value literal="BT_SCO" numerical="3"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForMediaType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="SPEAKER" numerical="1"/>
+            <value literal="HEADPHONES" numerical="2"/>
+            <value literal="BT_A2DP" numerical="4"/>
+            <value literal="WIRED_ACCESSORY" numerical="5"/>
+            <value literal="ANALOG_DOCK" numerical="8"/>
+            <value literal="DIGITAL_DOCK" numerical="9"/>
+            <value literal="NO_BT_A2DP" numerical="10"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForRecordType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="BT_SCO" numerical="3"/>
+            <value literal="WIRED_ACCESSORY" numerical="5"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForDockType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="WIRED_ACCESSORY" numerical="5"/>
+            <value literal="BT_CAR_DOCK" numerical="6"/>
+            <value literal="BT_DESK_DOCK" numerical="7"/>
+            <value literal="ANALOG_DOCK" numerical="8"/>
+            <value literal="DIGITAL_DOCK" numerical="9"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForSystemType" type="exclusive" >
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="SYSTEM_ENFORCED" numerical="11"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="HDMI_SYSTEM_AUDIO_ENFORCED" numerical="12"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="ENCODED_SURROUND_NEVER" numerical="13"/>
+            <value literal="ENCODED_SURROUND_ALWAYS" numerical="14"/>
+            <value literal="ENCODED_SURROUND_MANUAL" numerical="15"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="BT_SCO" numerical="3"/>
+        </values>
+    </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h b/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h
new file mode 100644
index 0000000..6c55a49
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h
@@ -0,0 +1,109 @@
+/*
+ * 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 <EngineConfig.h>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio_policy.h>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace capEngineConfig {
+
+static const char *const gCriterionTypeSuffix = "Type";
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+* Order MUST be aligned with definition of audio_policy_force_use_t within audio_policy.h
+*/
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
+    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
+    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
+    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
+    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
+    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
+    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
+    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
+};
+
+using ParameterValues = std::vector<std::string>;
+
+struct ConfigurableElement {
+    std::string path;
+};
+
+struct ConfigurableElementValue {
+    ConfigurableElement configurableElement;
+    std::string value;
+};
+using ConfigurableElementValues = std::vector<ConfigurableElementValue>;
+
+struct CapSetting {
+    std::string configurationName;
+    ConfigurableElementValues configurableElementValues;
+};
+using CapSettings = std::vector<CapSetting>;
+
+struct CapConfiguration {
+    std::string name;
+    std::string rule;
+};
+
+using ConfigurableElementPaths = std::vector<std::string>;
+using CapConfigurations = std::vector<CapConfiguration>;
+
+struct CapConfigurableDomain {
+    std::string name;
+    CapConfigurations configurations;
+    CapSettings settings;
+};
+
+struct CapCriterion {
+    engineConfig::Criterion criterion;
+    engineConfig::CriterionType criterionType;
+};
+
+using CapCriteria = std::vector<CapCriterion>;
+using CapConfigurableDomains = std::vector<CapConfigurableDomain>;
+
+struct CapConfig {
+    CapCriteria capCriteria;
+    CapConfigurableDomains capConfigurableDomains;
+};
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+    /** Parsed config, nullptr if the xml lib could not load the file */
+    std::unique_ptr<CapConfig> parsedConfig;
+    size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Convert the provided Cap Settings configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
+
+}
+}
diff --git a/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp b/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp
new file mode 100644
index 0000000..a1b4470
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp
@@ -0,0 +1,500 @@
+/*
+ * 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.
+ */
+
+#include <cinttypes>
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "APM::AudioPolicyEngine/CapConfig"
+//#define LOG_NDEBUG 0
+
+#include "CapEngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
+#include <cutils/properties.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using utilities::convertTo;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioHalCapCriterion;
+using media::audio::common::AudioHalCapParameter;
+using media::audio::common::AudioHalCapRule;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioHalCapCriterionV2;
+using ::android::base::unexpected;
+
+namespace capEngineConfig {
+
+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_";
+static constexpr const char *gPolicyParamPrefix = "/Policy/policy/";
+
+namespace {
+
+ConversionResult<std::string> truncatePrefixToLower(const std::string& legacyName,
+                                                    const std::string& legacyPrefix) {
+    std::size_t pos = legacyName.find(legacyPrefix);
+    if (pos == std::string::npos) {
+        return unexpected(BAD_VALUE);
+    }
+    std::string capName = legacyName.substr(pos + legacyPrefix.length());
+    std::transform(capName.begin(), capName.end(), capName.begin(),
+                   [](unsigned char c) { return std::tolower(c); });
+    return capName;
+}
+
+ConversionResult<std::string> truncatePrefix(const std::string& name,  const std::string& prefix) {
+    std::size_t pos = name.find(prefix);
+    if (pos == std::string::npos) {
+        return unexpected(BAD_VALUE);
+    }
+    std::string capName = name.substr(pos + prefix.length());
+    return capName;
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2_CapName(
+        const AudioHalCapCriterionV2& aidl) {
+    switch (aidl.getTag()) {
+        case AudioHalCapCriterionV2::availableInputDevices:
+            return gInputDeviceCriterionName;
+        case AudioHalCapCriterionV2::availableOutputDevices:
+            return gOutputDeviceCriterionName;
+        case AudioHalCapCriterionV2::availableInputDevicesAddresses:
+            return gInputDeviceAddressCriterionName;
+        case AudioHalCapCriterionV2::availableOutputDevicesAddresses:
+            return gOutputDeviceAddressCriterionName;
+        case AudioHalCapCriterionV2::telephonyMode:
+            return gPhoneStateCriterionName;
+        case AudioHalCapCriterionV2::forceConfigForUse: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
+            return gForceUseCriterionTag[VALUE_OR_RETURN(
+                    aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+                            aidlCriterion.forceUse))];
+        }
+        default:
+            return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
+        const AudioDeviceDescription& aidl) {
+    audio_devices_t legacyDeviceType = VALUE_OR_RETURN(
+            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl));
+    bool isOut = audio_is_output_devices(legacyDeviceType);
+    std::string legacyTypeLiteral;
+    if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
+        ALOGE("%s Invalid strategy device type %d", __func__, legacyDeviceType);
+        return unexpected(BAD_VALUE);
+    }
+    return truncatePrefix(legacyTypeLiteral,
+            isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix);
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
+        const AudioHalCapCriterionV2::Type& aidl) {
+    switch (aidl.getTag()) {
+        case AudioHalCapCriterionV2::Type::availableDevicesType:
+            return aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
+                    aidl.get<AudioHalCapCriterionV2::Type::availableDevicesType>());
+        case AudioHalCapCriterionV2::Type::availableDevicesAddressesType:
+            return aidl.get<AudioHalCapCriterionV2::Type::availableDevicesAddressesType>().template
+                    get<AudioDeviceAddress::id>();
+        case AudioHalCapCriterionV2::Type::telephonyModeType:
+            return toString(aidl.get<AudioHalCapCriterionV2::Type::telephonyModeType>());
+        case AudioHalCapCriterionV2::Type::forcedConfigType:
+            return toString(aidl.get<AudioHalCapCriterionV2::Type::forcedConfigType>());
+        default:
+            return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapRule_CapRule(
+        const AudioHalCapRule& aidlRule) {
+    std::string rule;
+    switch (aidlRule.compoundRule) {
+        case AudioHalCapRule::CompoundRule::ANY:
+            rule += "Any";
+            break;
+        case AudioHalCapRule::CompoundRule::ALL:
+            rule += "All";
+            break;
+        default:
+            return unexpected(BAD_VALUE);
+    }
+    rule += "{";
+    if (!aidlRule.nestedRules.empty()) {
+        for (const auto& nestedRule: aidlRule.nestedRules) {
+            rule += VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(nestedRule));
+        }
+        if (!aidlRule.criterionRules.empty()) {
+            rule += ",";
+        }
+    }
+    bool isFirstCriterionRule = true;
+    for (const auto& criterionRule: aidlRule.criterionRules) {
+        if (!isFirstCriterionRule) {
+            rule += ",";
+        }
+        isFirstCriterionRule = false;
+        std::string selectionCriterion = VALUE_OR_RETURN(
+                aidl2legacy_AudioHalCapCriterionV2_CapName(criterionRule.criterion));
+        std::string matchesWhen;
+        std::string value = VALUE_OR_RETURN(
+                aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
+                        criterionRule.criterionTypeValue));
+
+        switch (criterionRule.matchingRule) {
+            case AudioHalCapRule::MatchingRule::IS:
+                matchesWhen = "Is";
+                break;
+            case AudioHalCapRule::MatchingRule::IS_NOT:
+                matchesWhen = "IsNot";
+                break;
+            case AudioHalCapRule::MatchingRule::INCLUDES:
+                matchesWhen = "Includes";
+                break;
+            case AudioHalCapRule::MatchingRule::EXCLUDES:
+                matchesWhen = "Excludes";
+                break;
+            default:
+                return unexpected(BAD_VALUE);
+        }
+        rule += selectionCriterion + " " + matchesWhen + " " + value;
+    }
+    rule += "}";
+    return rule;
+}
+
+ConversionResult<CapConfiguration> aidl2legacy_AudioHalCapConfiguration_CapConfiguration(
+        const media::audio::common::AudioHalCapConfiguration& aidl) {
+    CapConfiguration legacy;
+    legacy.name = aidl.name;
+    legacy.rule = VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(aidl.rule));
+    return legacy;
+}
+
+ConversionResult<ConfigurableElementValue> aidl2legacy_ParameterSetting_ConfigurableElementValue(
+        const AudioHalCapParameter& aidl) {
+    ConfigurableElementValue legacy;
+    std::string literalValue;
+    switch (aidl.getTag()) {
+        case AudioHalCapParameter::selectedStrategyDevice: {
+            auto strategyDevice = aidl.get<AudioHalCapParameter::selectedStrategyDevice>();
+            literalValue = std::to_string(strategyDevice.isSelected);
+            audio_devices_t legacyType = VALUE_OR_RETURN(
+                    aidl2legacy_AudioDeviceDescription_audio_devices_t(strategyDevice.device));
+            std::string legacyTypeLiteral;
+            if (!::android::OutputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
+                ALOGE("%s Invalid device type %d", __func__, legacyType);
+                return unexpected(BAD_VALUE);
+            }
+            std::string deviceLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyTypeLiteral, gLegacyOutputDevicePrefix));
+            if (deviceLiteral == "default") {
+                deviceLiteral = "stub";
+            }
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix)
+                    + "product_strategies/vx_" + std::to_string(strategyDevice.id)
+                    + "/selected_output_devices/mask/" + deviceLiteral;
+            break;
+        }
+        case AudioHalCapParameter::strategyDeviceAddress: {
+            auto strategyAddress = aidl.get<AudioHalCapParameter::strategyDeviceAddress>();
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix)
+                    + "product_strategies/vx_" + std::to_string(strategyAddress.id)
+                    + "/device_address";
+            literalValue = strategyAddress.deviceAddress.get<AudioDeviceAddress::id>();
+            break;
+        }
+        case AudioHalCapParameter::selectedInputSourceDevice: {
+            auto inputSourceDevice = aidl.get<AudioHalCapParameter::selectedInputSourceDevice>();
+            literalValue = std::to_string(inputSourceDevice.isSelected);
+            audio_devices_t legacyType = VALUE_OR_RETURN(
+                    aidl2legacy_AudioDeviceDescription_audio_devices_t(inputSourceDevice.device));
+            std::string legacyTypeLiteral;
+            if (!::android::InputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
+                ALOGE("%s Invalid input source device type %d", __func__, legacyType);
+                return unexpected(BAD_VALUE);
+            }
+            std::string deviceLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyTypeLiteral, gLegacyInputDevicePrefix));
+            if (deviceLiteral == "default") {
+                deviceLiteral = "stub";
+            }
+            audio_source_t legacySource = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
+                    inputSourceDevice.inputSource));
+            std::string inputSourceLiteral;
+            if (!::android::SourceTypeConverter::toString(legacySource, inputSourceLiteral)) {
+                ALOGE("%s Invalid input source  %d", __func__, legacySource);
+                return unexpected(BAD_VALUE);
+            }
+            inputSourceLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(inputSourceLiteral, gLegacySourcePrefix));
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "input_sources/"
+                    + inputSourceLiteral + "/applicable_input_device/mask/" + deviceLiteral;
+            break;
+        }
+        case AudioHalCapParameter::streamVolumeProfile: {
+            auto streamVolumeProfile = aidl.get<AudioHalCapParameter::streamVolumeProfile>();
+            audio_stream_type_t legacyStreamType = VALUE_OR_RETURN(
+                    aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.stream));
+            std::string legacyStreamLiteral;
+            if (!::android::StreamTypeConverter::toString(legacyStreamType, legacyStreamLiteral)) {
+                ALOGE("%s Invalid stream type  %d", __func__, legacyStreamType);
+                return unexpected(BAD_VALUE);
+            }
+            legacyStreamLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyStreamLiteral, gLegacyStreamPrefix));
+
+            audio_stream_type_t legacyProfile = VALUE_OR_RETURN(
+                    aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.profile));
+            std::string legacyProfileLiteral;
+            if (!::android::StreamTypeConverter::toString(legacyProfile, legacyProfileLiteral)) {
+                ALOGE("%s Invalid profile %d", __func__, legacyProfile);
+                return unexpected(BAD_VALUE);
+            }
+            literalValue = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyProfileLiteral, gLegacyStreamPrefix));
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "streams/"
+                    + legacyStreamLiteral + "/applicable_volume_profile/volume_profile";
+            break;
+        }
+        default:
+            return unexpected(BAD_VALUE);
+    }
+    legacy.value = literalValue;
+    return legacy;
+}
+
+ConversionResult<CapSetting> aidl2legacy_AudioHalCapConfiguration_CapSetting(
+        const media::audio::common::AudioHalCapConfiguration& aidl) {
+    CapSetting legacy;
+    legacy.configurationName = aidl.name;
+    legacy.configurableElementValues = VALUE_OR_RETURN(convertContainer<ConfigurableElementValues>(
+            aidl.parameterSettings, aidl2legacy_ParameterSetting_ConfigurableElementValue));
+    return legacy;
+}
+
+ConversionResult<CapConfigurableDomain> aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(
+        const media::audio::common::AudioHalCapDomain& aidl) {
+    CapConfigurableDomain legacy;
+    legacy.name = aidl.name;
+    legacy.configurations = VALUE_OR_RETURN(convertContainer<CapConfigurations>(
+            aidl.configurations,
+            aidl2legacy_AudioHalCapConfiguration_CapConfiguration));
+    legacy.settings = VALUE_OR_RETURN(convertContainer<CapSettings>(
+            aidl.configurations,
+            aidl2legacy_AudioHalCapConfiguration_CapSetting));
+    return legacy;
+}
+
+ConversionResult<CapCriterion> aidl2legacy_AudioHalCapCriterionV2_Criterion(
+            const AudioHalCapCriterionV2& aidl) {
+    CapCriterion capCriterion;
+    engineConfig::Criterion& criterion = capCriterion.criterion;
+    engineConfig::CriterionType& criterionType = capCriterion.criterionType;
+
+    auto loadForceUseCriterion = [](const auto &aidlCriterion, auto &criterion,
+            auto &criterionType) -> status_t {
+        uint32_t legacyForceUse = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+                        aidlCriterion.forceUse));
+        criterion.typeName = criterionType.name;
+        criterionType.name = criterion.typeName + gCriterionTypeSuffix;
+        criterionType.isInclusive =
+                (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+        criterion.name = gForceUseCriterionTag[legacyForceUse];
+        criterion.defaultLiteralValue = toString(aidlCriterion.defaultValue);
+        if (aidlCriterion.values.empty()) {
+            return BAD_VALUE;
+        }
+        for (auto &value : aidlCriterion.values) {
+            uint32_t legacyForcedConfig = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(value));
+            criterionType.valuePairs.push_back({legacyForcedConfig, 0, toString(value)});
+        }
+        return NO_ERROR;
+    };
+
+    auto loadDevicesCriterion = [](const auto &aidlCriterion, auto &criterion,
+            auto &criterionType) -> status_t {
+        criterionType.name = criterion.name + gCriterionTypeSuffix;
+        criterionType.isInclusive =
+                (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+        criterion.typeName = criterionType.name;
+        int shift = 0;
+        if (aidlCriterion.values.empty()) {
+            return BAD_VALUE;
+        }
+        for (const auto &value : aidlCriterion.values) {
+            audio_devices_t legacyDeviceType = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioDeviceDescription_audio_devices_t(value));
+            bool isOut = audio_is_output_devices(legacyDeviceType);
+            std::string legacyTypeLiteral;
+            if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
+                ALOGE("%s Invalid device type %d", __func__, legacyDeviceType);
+                return BAD_VALUE;
+            }
+            std::string deviceLiteral = VALUE_OR_RETURN_STATUS(truncatePrefix(legacyTypeLiteral,
+                    isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix));
+            uint64_t pfwCriterionValue = 1 << shift++;
+            criterionType.valuePairs.push_back(
+                    {pfwCriterionValue, static_cast<int32_t>(legacyDeviceType), deviceLiteral});
+            ALOGV("%s: adding %" PRIu64 " %d %s %s", __func__, pfwCriterionValue, legacyDeviceType,
+                    toString(value.type).c_str(), deviceLiteral.c_str());
+        }
+        return NO_ERROR;
+    };
+
+    auto loadDeviceAddressesCriterion = [](const auto &aidlCriterion, auto &criterion,
+            auto &criterionType) -> status_t {
+        criterionType.name = criterion.name + gCriterionTypeSuffix;
+        criterionType.isInclusive =
+                (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+        criterion.typeName = criterionType.name;
+        int shift = 0;
+        for (auto &value : aidlCriterion.values) {
+            uint64_t pfwCriterionValue = 1 << shift++;
+            if (value.getTag() != AudioDeviceAddress::id) {
+                return BAD_VALUE;
+            }
+            std::string address = value.template get<AudioDeviceAddress::id>();
+            criterionType.valuePairs.push_back({pfwCriterionValue, 0, address});
+        }
+        return NO_ERROR;
+    };
+
+    switch (aidl.getTag()) {
+        case AudioHalCapCriterionV2::availableInputDevices: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableInputDevices>();
+            criterion.name = gInputDeviceCriterionName;
+            if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::availableOutputDevices: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableOutputDevices>();
+            criterion.name = gOutputDeviceCriterionName;
+            if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
+            auto aidlCriterion =
+                    aidl.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
+            criterion.name = gInputDeviceAddressCriterionName;
+            if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
+            auto aidlCriterion =
+                    aidl.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
+            criterion.name = gOutputDeviceAddressCriterionName;
+            if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::telephonyMode: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::telephonyMode>();
+            criterion.name = gPhoneStateCriterionName;
+            criterionType.name = criterion.name  + gCriterionTypeSuffix;
+            criterionType.isInclusive =
+                    (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+            criterion.typeName = criterionType.name;
+            criterion.defaultLiteralValue = toString( aidlCriterion.defaultValue);
+            if (aidlCriterion.values.empty()) {
+                return unexpected(BAD_VALUE);
+            }
+            for (auto &value : aidlCriterion.values) {
+                uint32_t legacyMode =
+                        VALUE_OR_RETURN(aidl2legacy_AudioMode_audio_mode_t(value));
+                criterionType.valuePairs.push_back({legacyMode, 0, toString(value)});
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::forceConfigForUse: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
+            if (loadForceUseCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        default:
+            return unexpected(BAD_VALUE);
+    }
+    return capCriterion;
+}
+
+}  // namespace
+
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+    auto config = std::make_unique<capEngineConfig::CapConfig>();
+
+    if (!aidlConfig.capSpecificConfig.has_value() ||
+            !aidlConfig.capSpecificConfig.value().domains.has_value()) {
+        ALOGE("%s: no Cap Engine config", __func__);
+        return ParsingResult{};
+    }
+    for (auto& aidlCriteria: aidlConfig.capSpecificConfig.value().criteriaV2.value()) {
+        if (aidlCriteria.has_value()) {
+            if (auto conv = aidl2legacy_AudioHalCapCriterionV2_Criterion(aidlCriteria.value());
+                    conv.ok()) {
+                config->capCriteria.push_back(std::move(conv.value()));
+            } else {
+                return ParsingResult{};
+            }
+        }
+    }
+    size_t skippedElement = 0;
+    for (auto& aidlDomain: aidlConfig.capSpecificConfig.value().domains.value()) {
+        if (aidlDomain.has_value()) {
+            if (auto conv = aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(aidlDomain.value());
+                    conv.ok()) {
+                config->capConfigurableDomains.push_back(std::move(conv.value()));
+            } else {
+                return ParsingResult{};
+            }
+        } else {
+            skippedElement += 1;
+        }
+    }
+    return {.parsedConfig=std::move(config), .nbSkippedElement=skippedElement};
+}
+} // namespace capEngineConfig
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/data/Android.bp b/services/audiopolicy/engineconfigurable/data/Android.bp
new file mode 100644
index 0000000..303cabc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/Android.bp
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_av_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_license"],
+}
+
+prebuilt_etc {
+    name: "CapClass.xml",
+    src: ":CapClass",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "CapSubsystem.xml",
+    src: ":CapSubsystem",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "CapSubsystem-CommonTypes.xml",
+    src: ":buildaidlcommontypesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "CapProductStrategies.xml",
+    src: ":cap_product_strategies_structure",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "ParameterFrameworkConfigurationCap.xml",
+    src: ":ParameterFrameworkConfigurationCapSrc_gen",
+    sub_dir: "parameter-framework",
+}
+
+genrule {
+    name: "ParameterFrameworkConfigurationCapSrc_gen",
+    out: ["ParameterFrameworkConfigurationCap.xml"],
+    srcs: [":ParameterFrameworkConfigurationCapSrc"],
+    product_variables: {
+        debuggable: {
+            cmd: "sed -e 's|TuningAllowed=\"false\"|TuningAllowed=\"true\" ServerPort=\"unix:///dev/socket/audioserver/policy_debug\"|g' <$(in) > $(out)",
+        },
+    },
+    cmd: "cp -f $(in) $(out)",
+}
+
+genrule {
+    name: "buildaidlcommontypesstructure_gen",
+    defaults: ["buildcommontypesstructurerule"],
+    out: ["CapSubsystem-CommonTypes.xml"],
+}
+
+filegroup {
+    name: "ParameterFrameworkConfigurationCapSrc",
+    srcs: ["etc/ParameterFrameworkConfigurationCap.xml"],
+}
+
+filegroup {
+    name: "cap_product_strategies_structure",
+    srcs: ["etc/Structure/CapProductStrategies.xml"],
+}
+
+filegroup {
+    name: "CapSubsystem",
+    srcs: ["etc/Structure/CapSubsystem.xml"],
+}
+
+filegroup {
+    name: "aidl_common_types_structure_template",
+    srcs: ["etc/Structure/CapSubsystem-CommonTypes.xml.in"],
+}
+
+filegroup {
+    name: "CapClass",
+    srcs: ["etc/Structure/CapClass.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml b/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml
new file mode 100644
index 0000000..bac7a25
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    SystemClassName="Policy" TuningAllowed="false">
+
+    <SubsystemPlugins>
+        <Location Folder="">
+            <Plugin Name="libpolicy-subsystem.so"/>
+        </Location>
+    </SubsystemPlugins>
+    <StructureDescriptionFileLocation Path="Structure/Policy/CapClass.xml"/>
+</ParameterFrameworkConfiguration>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml
new file mode 100644
index 0000000..e233673
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<SystemClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../Schemas/SystemClass.xsd" Name="Policy">
+    <SubsystemInclude Path="CapSubsystem.xml"/>
+</SystemClass>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml
new file mode 100644
index 0000000..61f056a
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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.
+-->
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xi="http://www.w3.org/2001/XInclude"
+              xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+  <!-- This structure is expected to be in the system partition and provisionned a maximum
+       allowed strategies to be used by vendor. -->
+  <ComponentType Name="ProductStrategies" Description="">
+    <Component Name="vx_1000" Type="ProductStrategy" Mapping="Identifier:1000,Name:vx_1000"/>
+    <Component Name="vx_1001" Type="ProductStrategy" Mapping="Identifier:1001,Name:vx_1001"/>
+    <Component Name="vx_1002" Type="ProductStrategy" Mapping="Identifier:1002,Name:vx_1002"/>
+    <Component Name="vx_1003" Type="ProductStrategy" Mapping="Identifier:1003,Name:vx_1003"/>
+    <Component Name="vx_1004" Type="ProductStrategy" Mapping="Identifier:1004,Name:vx_1004"/>
+    <Component Name="vx_1005" Type="ProductStrategy" Mapping="Identifier:1005,Name:vx_1005"/>
+    <Component Name="vx_1006" Type="ProductStrategy" Mapping="Identifier:1006,Name:vx_1006"/>
+    <Component Name="vx_1007" Type="ProductStrategy" Mapping="Identifier:1007,Name:vx_1007"/>
+    <Component Name="vx_1008" Type="ProductStrategy" Mapping="Identifier:1008,Name:vx_1008"/>
+    <Component Name="vx_1009" Type="ProductStrategy" Mapping="Identifier:1009,Name:vx_1009"/>
+    <Component Name="vx_1010" Type="ProductStrategy" Mapping="Identifier:1010,Name:vx_1010"/>
+    <Component Name="vx_1011" Type="ProductStrategy" Mapping="Identifier:1011,Name:vx_1011"/>
+    <Component Name="vx_1012" Type="ProductStrategy" Mapping="Identifier:1012,Name:vx_1012"/>
+    <Component Name="vx_1013" Type="ProductStrategy" Mapping="Identifier:1013,Name:vx_1013"/>
+    <Component Name="vx_1014" Type="ProductStrategy" Mapping="Identifier:1014,Name:vx_1014"/>
+    <Component Name="vx_1015" Type="ProductStrategy" Mapping="Identifier:1015,Name:vx_1015"/>
+    <Component Name="vx_1016" Type="ProductStrategy" Mapping="Identifier:1016,Name:vx_1016"/>
+    <Component Name="vx_1017" Type="ProductStrategy" Mapping="Identifier:1017,Name:vx_1017"/>
+    <Component Name="vx_1018" Type="ProductStrategy" Mapping="Identifier:1018,Name:vx_1018"/>
+    <Component Name="vx_1019" Type="ProductStrategy" Mapping="Identifier:1019,Name:vx_1019"/>
+    <Component Name="vx_1020" Type="ProductStrategy" Mapping="Identifier:1020,Name:vx_1020"/>
+    <Component Name="vx_1021" Type="ProductStrategy" Mapping="Identifier:1021,Name:vx_1021"/>
+    <Component Name="vx_1022" Type="ProductStrategy" Mapping="Identifier:1022,Name:vx_1022"/>
+    <Component Name="vx_1023" Type="ProductStrategy" Mapping="Identifier:1023,Name:vx_1023"/>
+    <Component Name="vx_1024" Type="ProductStrategy" Mapping="Identifier:1024,Name:vx_1024"/>
+    <Component Name="vx_1025" Type="ProductStrategy" Mapping="Identifier:1025,Name:vx_1025"/>
+    <Component Name="vx_1026" Type="ProductStrategy" Mapping="Identifier:1026,Name:vx_1026"/>
+    <Component Name="vx_1027" Type="ProductStrategy" Mapping="Identifier:1027,Name:vx_1027"/>
+    <Component Name="vx_1028" Type="ProductStrategy" Mapping="Identifier:1028,Name:vx_1028"/>
+    <Component Name="vx_1029" Type="ProductStrategy" Mapping="Identifier:1029,Name:vx_1029"/>
+    <Component Name="vx_1030" Type="ProductStrategy" Mapping="Identifier:1030,Name:vx_1030"/>
+    <Component Name="vx_1031" Type="ProductStrategy" Mapping="Identifier:1031,Name:vx_1031"/>
+    <Component Name="vx_1032" Type="ProductStrategy" Mapping="Identifier:1032,Name:vx_1032"/>
+    <Component Name="vx_1033" Type="ProductStrategy" Mapping="Identifier:1033,Name:vx_1033"/>
+    <Component Name="vx_1034" Type="ProductStrategy" Mapping="Identifier:1034,Name:vx_1034"/>
+    <Component Name="vx_1035" Type="ProductStrategy" Mapping="Identifier:1035,Name:vx_1035"/>
+    <Component Name="vx_1036" Type="ProductStrategy" Mapping="Identifier:1036,Name:vx_1036"/>
+    <Component Name="vx_1037" Type="ProductStrategy" Mapping="Identifier:1037,Name:vx_1037"/>
+    <Component Name="vx_1038" Type="ProductStrategy" Mapping="Identifier:1038,Name:vx_1038"/>
+    <Component Name="vx_1039" Type="ProductStrategy" Mapping="Identifier:1039,Name:vx_1039"/>
+  </ComponentType>
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in
new file mode 100644
index 0000000..2c4c7b5
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xi="http://www.w3.org/2001/XInclude"
+              xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+    <!-- Output devices definition as a bitfield for the supported devices per output
+    profile. It must match with the output device enum parameter.
+    -->
+     <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+
+     <!--#################### GLOBAL COMPONENTS END ####################-->
+
+    <!-- Automatically filled from audio-base.h file -->
+    <ComponentType Name="OutputDevicesMask" Description="64bit representation of devices">
+        <BitParameterBlock Name="mask" Size="64">
+        </BitParameterBlock>
+    </ComponentType>
+
+    <!-- Input devices definition as a bitfield for the supported devices per Input
+    profile. It must match with the Input device enum parameter.
+    -->
+    <!-- Automatically filled from audio-base.h file -->
+    <ComponentType Name="InputDevicesMask" Description="64bit representation of devices">
+        <BitParameterBlock Name="mask" Size="64">
+        </BitParameterBlock>
+    </ComponentType>
+
+    <!--#################### STREAM COMMON TYPES BEGIN ####################-->
+    <!-- Automatically filled from audio-base.h file. VolumeProfileType is associated to stream type -->
+    <ComponentType Name="VolumeProfileType">
+        <EnumParameter Name="volume_profile" Size="32">
+        </EnumParameter>
+    </ComponentType>
+
+    <ComponentType Name="Stream"  Mapping="Stream">
+        <Component Name="applicable_volume_profile" Type="VolumeProfileType"
+                   Description="Volume profile followed by a given stream type."/>
+    </ComponentType>
+
+    <!--#################### STREAM COMMON TYPES END ####################-->
+
+    <!--#################### INPUT SOURCE COMMON TYPES BEGIN ####################-->
+
+    <ComponentType Name="InputSource">
+        <Component Name="applicable_input_device" Type="InputDevicesMask"
+                   Mapping="InputSource" Description="Selected Input device"/>
+    </ComponentType>
+
+    <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
+
+    <!--#################### PRODUCT STRATEGY COMMON TYPES BEGIN ####################-->
+
+    <ComponentType Name="ProductStrategy" Mapping="ProductStrategy">
+        <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
+        <StringParameter Name="device_address" MaxLength="256"
+                         Description="if any, device address associated"/>
+    </ComponentType>
+
+    <!--#################### PRODUCT STRATEGY COMMON TYPES END ####################-->
+
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml
new file mode 100644
index 0000000..45a0bd4
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<Subsystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:xi="http://www.w3.org/2001/XInclude"
+           xsi:noNamespaceSchemaLocation="Schemas/Subsystem.xsd"
+           Name="policy" Type="Policy">
+
+    <ComponentLibrary>
+        <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+        <!-- Common Types definition -->
+        <xi:include href="CapSubsystem-CommonTypes.xml"/>
+        <xi:include href="CapProductStrategies.xml"/>
+
+
+        <!--#################### GLOBAL COMPONENTS END ####################-->
+
+        <!--#################### STREAM BEGIN ####################-->
+
+        <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+            <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+            <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+            <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+            <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+            <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+            <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+            <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+                       Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+            <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+            <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+                             Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+            <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
+                             Description="For accessibility talk back prompts"/>
+            <Component Name="assistant" Type="Stream" Mapping="Name:AUDIO_STREAM_ASSISTANT"
+                             Description="used by a virtual assistant like Google Assistant, Bixby, etc."/>
+            <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
+                             Description="For dynamic policy output mixes"/>
+            <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
+                             Description="For internal audio flinger tracks. Fixed volume"/>
+        </ComponentType>
+
+        <!--#################### STREAM END ####################-->
+
+        <!--#################### INPUT SOURCE BEGIN ####################-->
+
+        <ComponentType Name="InputSources" Description="associated to audio_source_t definition,
+                             identifier mapping must match the value of the enum">
+            <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+            <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
+            <Component Name="voice_uplink" Type="InputSource"
+                                           Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
+            <Component Name="voice_downlink" Type="InputSource"
+                                             Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
+            <Component Name="voice_call" Type="InputSource"
+                                         Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+            <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
+            <Component Name="voice_recognition" Type="InputSource"
+                                                Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
+            <Component Name="voice_communication" Type="InputSource"
+                                                  Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+            <Component Name="remote_submix" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
+            <Component Name="unprocessed" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+            <Component Name="voice_performance" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+            <Component Name="echo_reference" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_ECHO_REFERENCE"/>
+            <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
+            <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
+        </ComponentType>
+        <!--#################### INPUT SOURCE END ####################-->
+    </ComponentLibrary>
+
+    <InstanceDefinition>
+        <Component Name="streams" Type="Streams"/>
+        <Component Name="input_sources" Type="InputSources"/>
+        <Component Name="product_strategies" Type="ProductStrategies"/>
+    </InstanceDefinition>
+</Subsystem>
diff --git a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
index 9fd8b8e..e0b7210 100644
--- a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
+++ b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
@@ -98,7 +98,8 @@
     virtual bool setDeviceTypesForProductStrategy(product_strategy_t strategy,
                                                   uint64_t devices) = 0;
 
-    virtual product_strategy_t getProductStrategyByName(const std::string &address) = 0;
+    virtual product_strategy_t getProductStrategyByName(const std::string &name) = 0;
+    virtual std::string getProductStrategyName(product_strategy_t id) const = 0;
 
 protected:
     virtual ~AudioPolicyPluginInterface() {}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
index 7fe111f..e4f44d5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
@@ -50,6 +50,7 @@
 genrule {
     name: "buildcommontypesstructure_gen",
     defaults: ["buildcommontypesstructurerule"],
+    out: ["PolicySubsystem-CommonTypes.xml"],
 }
 
 filegroup {
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 8bd7f66..bf5767d 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -72,7 +72,7 @@
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<ProductStrategy>(
-            mProductStrategyComponentName, (1 << MappingKeyName))
+            mProductStrategyComponentName, (1 << MappingKeyName) | (1 << MappingKeyIdentifier))
         );
 }
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
index ebd9456..06efbf28 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
@@ -18,10 +18,7 @@
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
 
-using std::string;
-using android::product_strategy_t;
-
-ProductStrategy::ProductStrategy(const string &mappingValue,
+ProductStrategy::ProductStrategy(const std::string &mappingValue,
                    CInstanceConfigurableElement *instanceConfigurableElement,
                    const CMappingContext &context,
                    core::log::Logger& logger)
@@ -30,26 +27,32 @@
                                 mappingValue,
                                 MappingKeyAmend1,
                                 (MappingKeyAmendEnd - MappingKeyAmend1 + 1),
-                                context)
-{
-    std::string name(context.getItem(MappingKeyName));
+                                context) {
+
+    size_t id = context.getItemAsInteger(MappingKeyIdentifier);
+    std::string nameFromStructure(context.getItem(MappingKeyName));
 
     ALOG_ASSERT(instanceConfigurableElement != nullptr, "Invalid Configurable Element");
     mPolicySubsystem = static_cast<const PolicySubsystem *>(
-                instanceConfigurableElement->getBelongingSubsystem());
+            instanceConfigurableElement->getBelongingSubsystem());
     ALOG_ASSERT(mPolicySubsystem != nullptr, "Invalid Policy Subsystem");
 
     mPolicyPluginInterface = mPolicySubsystem->getPolicyPluginInterface();
     ALOG_ASSERT(mPolicyPluginInterface != nullptr, "Invalid Policy Plugin Interface");
 
-    mId = mPolicyPluginInterface->getProductStrategyByName(name);
+    mId = static_cast<android::product_strategy_t>(id);
+    std::string name = mPolicyPluginInterface->getProductStrategyName(mId);
+    if (name.empty()) {
+        name = nameFromStructure;
+        mId = mPolicyPluginInterface->getProductStrategyByName(name);
+    }
 
     ALOG_ASSERT(mId != PRODUCT_STRATEGY_INVALID, "Product Strategy %s not found", name.c_str());
 
     ALOGE("Product Strategy %s added", name.c_str());
 }
 
-bool ProductStrategy::sendToHW(string & /*error*/)
+bool ProductStrategy::sendToHW(std::string & /*error*/)
 {
     Device deviceParams;
     blackboardRead(&deviceParams, sizeof(deviceParams));
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index ccd4316..45da7b0 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -71,27 +71,75 @@
 }
 
 status_t Engine::loadFromHalConfigWithFallback(
-        const media::audio::common::AudioHalEngineConfig& config __unused) {
-    // b/242678729. Need to implement for the configurable engine.
-    return INVALID_OPERATION;
-}
+        const media::audio::common::AudioHalEngineConfig& aidlConfig) {
 
-status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
-{
-    status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
-    if (loadResult < 0) {
-        ALOGE("Policy Engine configuration is invalid.");
+    auto capResult = capEngineConfig::convert(aidlConfig);
+    if (capResult.parsedConfig == nullptr) {
+        ALOGE("%s CapEngine Config invalid", __func__);
+        return BAD_VALUE;
     }
-    return loadResult;
-}
-
-status_t Engine::initCheck()
-{
+    status_t ret = loadWithFallback(aidlConfig);
+    if (ret != NO_ERROR) {
+        return ret;
+    }
+    auto loadCriteria= [this](const auto& capCriteria) {
+        for (auto& capCriterion : capCriteria) {
+            mPolicyParameterMgr->addCriterion(capCriterion.criterion.name,
+                    capCriterion.criterionType.isInclusive,
+                    capCriterion.criterionType.valuePairs,
+                    capCriterion.criterion.defaultLiteralValue);
+        }
+    };
+    loadCriteria(capResult.parsedConfig->capCriteria);
     std::string error;
     if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
         ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
         return NO_INIT;
     }
+    return mPolicyParameterMgr->setConfiguration(capResult);
+}
+
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
+{
+    status_t status = loadWithFallback(xmlFilePath);
+    std::string error;
+    if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
+        ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
+        return NO_INIT;
+    }
+    return status;
+}
+
+template<typename T>
+status_t Engine::loadWithFallback(const T& configSource) {
+    auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
+    ALOGE_IF(result.nbSkippedElement != 0,
+             "Policy Engine configuration is partially invalid, skipped %zu elements",
+             result.nbSkippedElement);
+
+    auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
+        for (auto& criterion : configCriteria) {
+            engineConfig::CriterionType criterionType;
+            for (auto &configCriterionType : configCriterionTypes) {
+                if (configCriterionType.name == criterion.typeName) {
+                    criterionType = configCriterionType;
+                    break;
+                }
+            }
+            ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
+                        criterion.name.c_str());
+            mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
+                                              criterionType.valuePairs,
+                                              criterion.defaultLiteralValue);
+        }
+    };
+
+    loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
+    return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
+status_t Engine::initCheck()
+{
     return EngineBase::initCheck();
 }
 
@@ -199,32 +247,6 @@
     return EngineBase::setDeviceConnectionState(device, state);
 }
 
-status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
-{
-    auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
-
-    // Custom XML Parsing
-    auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
-        for (auto& criterion : configCriteria) {
-            engineConfig::CriterionType criterionType;
-            for (auto &configCriterionType : configCriterionTypes) {
-                if (configCriterionType.name == criterion.typeName) {
-                    criterionType = configCriterionType;
-                    break;
-                }
-            }
-            ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
-                        criterion.name.c_str());
-            mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
-                                              criterionType.valuePairs,
-                                              criterion.defaultLiteralValue);
-        }
-    };
-
-    loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
-    return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
-}
-
 status_t Engine::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
                                            const AudioDeviceTypeAddrVector &devices)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4f3e620..d9ebbe7 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -16,10 +16,11 @@
 
 #pragma once
 
-#include "EngineBase.h"
-#include <EngineInterface.h>
-#include <AudioPolicyPluginInterface.h>
 #include "Collection.h"
+#include "EngineBase.h"
+#include <AudioPolicyPluginInterface.h>
+#include <CapEngineConfig.h>
+#include <EngineInterface.h>
 
 namespace android {
 class AudioPolicyManagerObserver;
@@ -107,8 +108,14 @@
     {
         return EngineBase::getProductStrategyByName(name);
     }
+    std::string getProductStrategyName(product_strategy_t id) const override {
+        return EngineBase::getProductStrategyName(id);
+    }
 
 private:
+    template<typename T>
+    status_t loadWithFallback(const T& configSource);
+
     android::status_t disableDevicesForStrategy(product_strategy_t strategy,
             const DeviceVector &devicesToDisable);
     void enableDevicesForStrategy(product_strategy_t strategy, const DeviceVector &devicesToEnable);
@@ -140,8 +147,6 @@
     template <typename Property, typename Key>
     bool setPropertyForKey(const Property &property, const Key &key);
 
-    status_t loadAudioPolicyEngineConfig(const std::string& xmlFilePath);
-
     DeviceVector getCachedDevices(product_strategy_t ps) const;
 
     ///
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index d1fb2fb..7ae124c 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -23,7 +23,7 @@
 }
 
 //##################################################################################################
-// Tools for audio policy engine criterion type configuration file
+// Legacy tools for audio policy engine criterion type configuration file
 //
 python_binary_host {
     name: "buildPolicyCriterionTypes",
@@ -57,6 +57,40 @@
 }
 
 //##################################################################################################
+// Tools for audio policy engine criterion type configuration file
+//
+python_binary_host {
+    name: "capBuildPolicyCriterionTypes",
+    main: "capBuildPolicyCriterionTypes.py",
+    srcs: [
+        "capBuildPolicyCriterionTypes.py",
+    ],
+}
+
+genrule_defaults {
+    name: "capbuildpolicycriteriontypesrule",
+    tools: ["capBuildPolicyCriterionTypes"],
+    cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
+        "cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
+        "$(location capBuildPolicyCriterionTypes) " +
+        " --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
+        " --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
+        "--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
+        "--criteriontypes $(location :audio_policy_engine_aidl_criterion_types_template) " +
+        "--outputfile $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // @todo uncomment if 1428659 is merged":android_audio_base_header_file",
+        ":audio_policy_engine_aidl_criterion_types_template",
+        ":libaudio_system_audio_base",
+        ":libaudio_system_audio_common_base",
+        // ":audio_policy_configuration_top_file",
+        // ":audio_policy_configuration_files",
+    ],
+    out: ["audio_policy_engine_criterion_types.xml"],
+}
+
+//##################################################################################################
 // Tools for audio policy engine parameter framework configurable domains
 //
 python_binary_host {
@@ -84,6 +118,7 @@
     cmd: "mkdir -p $(genDir)/Structure/Policy && " +
         "cp $(locations :audio_policy_pfw_structure_files) $(genDir)/Structure/Policy && " +
         "cp $(location :audio_policy_pfw_toplevel) $(genDir)/top_level && " +
+        "sed -i -e 's|TuningAllowed=\"false\"|TuningAllowed=\"true\" ServerPort=\"unix:///dev/socket/audioserver/policy_debug\"|g' $(genDir)/top_level &&" +
         "$(location domainGeneratorPolicy) " +
         "--validate " +
         "--domain-generator-tool $(location domainGeneratorConnector) " +
@@ -106,7 +141,7 @@
 }
 
 //##################################################################################################
-// Tools for policy parameter-framework product strategies structure file generation
+// Legacy tools for policy parameter-framework product strategies structure file generation
 //
 python_binary_host {
     name: "buildStrategiesStructureFile",
@@ -154,5 +189,4 @@
         ":common_types_structure_template",
         ":libaudio_system_audio_base",
     ],
-    out: ["PolicySubsystem-CommonTypes.xml"],
 }
diff --git a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
index f69d346..6eabc57 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
@@ -75,7 +75,7 @@
     strategy_components = strategies_root.find('ComponentType')
 
     for strategy_name in strategies:
-        context_mapping = "".join(map(str, ["Name:", strategy_name]))
+        context_mapping = "".join(map(str, ["Identifier:-1,Name:", strategy_name]))
         strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower()
         ET.SubElement(strategy_components, "Component",
                       Name=strategy_pfw_name, Type="ProductStrategy",
diff --git a/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py
new file mode 100755
index 0000000..b873830
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py
@@ -0,0 +1,368 @@
+#!/usr/bin/python3
+
+#
+# Copyright 2018, 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.
+#
+
+import argparse
+import re
+import sys
+import os
+import logging
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+#           --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+#           --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+#           --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+#           --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+def parseArgs():
+    argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+                                        audio criterion type file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occurred.")
+    argparser.add_argument('--androidaudiobaseheader',
+                           help="Android Audio Base C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--androidaudiocommonbaseheader',
+                           help="Android Audio CommonBase C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_COMMON_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--audiopolicyconfigurationfile',
+                           help="Android Audio Policy Configuration file, Mandatory.",
+                           metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--criteriontypes',
+                           help="Criterion types XML base file, in \
+                           '<criterion_types> \
+                               <criterion_type name="" type=<inclusive|exclusive> \
+                               values=<value1,value2,...>/>' \
+                           format. Mandatory.",
+                           metavar="CRITERION_TYPE_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--outputfile',
+                           help="Criterion types outputfile file. Mandatory.",
+                           metavar="CRITERION_TYPE_OUTPUT_FILE",
+                           type=argparse.FileType('w'),
+                           required=True)
+    argparser.add_argument('--verbose',
+                           action='store_true')
+
+    return argparser.parse_args()
+
+
+output_devices_type_value = {}
+input_devices_type_value = {}
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+    logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+    criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+    criterion_types_root = criterion_types_in_tree.getroot()
+
+    for criterion_name, values_dict in criterionTypes.items():
+        for criterion_type in criterion_types_root.findall('criterion_type'):
+            if criterion_type.get('name') == criterion_name:
+                values_node = ET.SubElement(criterion_type, "values")
+                ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+                for key, value in ordered_values.items():
+                    value_node = ET.SubElement(values_node, "value")
+                    value_node.set('numerical', str(value))
+                    value_node.set('literal', key)
+
+                    if criterion_type.get('name') == "OutputDevicesMaskType":
+                        value_node.set('android_type', output_devices_type_value[key])
+                    if criterion_type.get('name') == "InputDevicesMaskType":
+                        value_node.set('android_type', input_devices_type_value[key])
+
+    if addressCriteria:
+        for criterion_name, values_list in addressCriteria.items():
+            for criterion_type in criterion_types_root.findall('criterion_type'):
+                if criterion_type.get('name') == criterion_name:
+                    index = 0
+                    existing_values_node = criterion_type.find("values")
+                    if existing_values_node is not None:
+                        for existing_value in existing_values_node.findall('value'):
+                            if existing_value.get('numerical') == str(1 << index):
+                                index += 1
+                        values_node = existing_values_node
+                    else:
+                        values_node = ET.SubElement(criterion_type, "values")
+
+                    for value in values_list:
+                        value_node = ET.SubElement(values_node, "value", literal=value)
+                        value_node.set('numerical', str(1 << index))
+                        index += 1
+
+    xmlstr = ET.tostring(criterion_types_root, encoding='utf8', method='xml')
+    reparsed = MINIDOM.parseString(xmlstr)
+    prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+    prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+    outputFile.write(prettyXmlStr)
+
+def capitalizeLine(line):
+    return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+    logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+    #
+    # extract all devices addresses from audio policy configuration file
+    #
+    address_criteria_mapping_table = {
+        'sink' : "OutputDevicesAddressesType",
+        'source' : "InputDevicesAddressesType"}
+
+    address_criteria = {
+        'OutputDevicesAddressesType' : [],
+        'InputDevicesAddressesType' : []}
+
+    old_working_dir = os.getcwd()
+    print("Current working directory %s" % old_working_dir)
+
+    new_dir = os.path.join(old_working_dir, audiopolicyconfigurationfile.name)
+
+    policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+    os.chdir(os.path.dirname(os.path.normpath(new_dir)))
+
+    print("new working directory %s" % os.getcwd())
+
+    policy_root = policy_in_tree.getroot()
+    EI.include(policy_root)
+
+    os.chdir(old_working_dir)
+
+    for device in policy_root.iter('devicePort'):
+        for key in address_criteria_mapping_table.keys():
+            if device.get('role') == key and device.get('address'):
+                logging.info("{}: <{}>".format(key, device.get('address')))
+                address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
+
+    for criteria in address_criteria:
+        values = ','.join(address_criteria[criteria])
+        logging.info("{}: <{}>".format(criteria, values))
+
+    return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+#   -Android Mode
+#   -Output devices type
+#   -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile, androidaudiocommonbaseheaderFile):
+    #
+    # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+    #
+    criterion_mapping_table = {
+        'HAL_AUDIO_MODE' : "AndroidModeType",
+        'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+        'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+    all_criteria = {
+        'AndroidModeType' : {},
+        'OutputDevicesMaskType' : {},
+        'InputDevicesMaskType' : {}}
+
+    #
+    # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+    #
+    ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
+
+    multi_bit_outputdevice_shift = 32
+    multi_bit_inputdevice_shift = 32
+
+    criteria_pattern = re.compile(
+        r"\s*V\((?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+        r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*,\s*" \
+        r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+    logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+    for line_number, line in enumerate(androidaudiobaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiobaseheaderFile.name, line_number, line))
+
+            criterion_name = criterion_mapping_table[match.groupdict()['type']]
+            criterion_literal = ''.join(match.groupdict()['literal'])
+            criterion_numerical_value = match.groupdict()['values']
+
+            if criterion_name == "InputDevicesMaskType":
+                # Remove ambient and in_communication since they were deprecated
+                logging.info("Remove deprecated device {}".format(criterion_literal))
+                if criterion_literal == "AMBIENT" or criterion_literal == "COMMUNICATION":
+                    logging.info("Remove deprecated device {}".format(criterion_literal))
+                    continue
+                # for AUDIO_DEVICE_IN: rename default to stub
+                elif criterion_literal == "DEFAULT":
+                    criterion_numerical_value = str(int("0x40000000", 0))
+                    input_devices_type_value[criterion_literal] = "0xC0000000"
+                else:
+                    try:
+                        string_int = int(criterion_numerical_value, 0)
+                        # Append AUDIO_DEVICE_IN for android type tag
+                        input_devices_type_value[criterion_literal] = hex(string_int | 2147483648)
+
+                        num_bits = bin(string_int).count("1")
+                        if num_bits > 1:
+                            logging.info("The value {}:{} is for criterion {} binary rep {} has {} bits sets"
+                                .format(criterion_numerical_value, criterion_literal, criterion_name, bin(string_int), num_bits))
+                            string_int = 2**multi_bit_inputdevice_shift
+                            logging.info("new val assigned is {} {}" .format(string_int, bin(string_int)))
+                            multi_bit_inputdevice_shift += 1
+                            criterion_numerical_value = str(string_int)
+
+                    except ValueError:
+                        # Handle the exception
+                        logging.info("value {}:{} for criterion {} is not a number, ignoring"
+                            .format(criterion_numerical_value, criterion_literal, criterion_name))
+                        continue
+
+            if criterion_name == "OutputDevicesMaskType":
+                if criterion_literal == "DEFAULT":
+                    criterion_numerical_value = str(int("0x40000000", 0))
+                    output_devices_type_value[criterion_literal] = "0x40000000"
+                else:
+                    try:
+                        string_int = int(criterion_numerical_value, 0)
+                        output_devices_type_value[criterion_literal] = criterion_numerical_value
+
+                        num_bits = bin(string_int).count("1")
+                        if num_bits > 1:
+                            logging.info("The value {}:{} is for criterion {} binary rep {} has {} bits sets"
+                                .format(criterion_numerical_value, criterion_literal, criterion_name, bin(string_int), num_bits))
+                            string_int = 2**multi_bit_outputdevice_shift
+                            logging.info("new val assigned is {} {}" .format(string_int, bin(string_int)))
+                            multi_bit_outputdevice_shift += 1
+                            criterion_numerical_value = str(string_int)
+
+                    except ValueError:
+                        # Handle the exception
+                        logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+                            .format(criterion_numerical_value, criterion_literal, criterion_name))
+                        continue
+
+            try:
+                string_int = int(criterion_numerical_value, 0)
+
+            except ValueError:
+                # Handle the exception
+                logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+                    .format(criterion_numerical_value, criterion_literal, criterion_name))
+                continue
+
+            # Remove duplicated numerical values
+            if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+                logging.info("criterion {} duplicated values:".format(criterion_name))
+                logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+                logging.info("KEEPING LATEST")
+                for key in list(all_criteria[criterion_name]):
+                    if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+                        del all_criteria[criterion_name][key]
+
+            all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+            logging.debug("type:{},".format(criterion_name))
+            logging.debug("iteral:{},".format(criterion_literal))
+            logging.debug("values:{}.".format(criterion_numerical_value))
+
+    logging.info("Checking Android Common Header file {}".format(androidaudiocommonbaseheaderFile))
+
+    criteria_pattern = re.compile(
+        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+        r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+        r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+    for line_number, line in enumerate(androidaudiocommonbaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiocommonbaseheaderFile.name, line_number, line))
+
+            criterion_name = criterion_mapping_table[match.groupdict()['type']]
+            criterion_literal = ''.join(match.groupdict()['literal'])
+            criterion_numerical_value = match.groupdict()['values']
+
+            try:
+                string_int = int(criterion_numerical_value, 0)
+            except ValueError:
+                # Handle the exception
+                logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+                    .format(criterion_numerical_value, criterion_literal, criterion_name))
+                continue
+
+            # Remove duplicated numerical values
+            if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+                logging.info("criterion {} duplicated values:".format(criterion_name))
+                logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+                logging.info("KEEPING LATEST")
+                for key in list(all_criteria[criterion_name]):
+                    if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+                        del all_criteria[criterion_name][key]
+
+            all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+            logging.debug("type:{},".format(criterion_name))
+            logging.debug("iteral:{},".format(criterion_literal))
+            logging.debug("values:{}.".format(criterion_numerical_value))
+
+    return all_criteria
+
+
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+
+    all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader,
+                                         args.androidaudiocommonbaseheader)
+
+    address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+    criterion_types = args.criteriontypes
+
+    generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.bp b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
index 78d5fa3..506b19b 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.bp
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
@@ -19,10 +19,12 @@
     ],
     header_libs: [
         "libaudiofoundation_headers",
+        "libaudiopolicycapengine_config_headers",
         "libaudiopolicycommon",
         "libbase_headers",
     ],
     shared_libs: [
+        "libaudiopolicyengine_config",
         "liblog",
         "libmedia_helper",
         "libparameter",
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 099d55d..0bcde8d 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,13 +18,13 @@
 //#define LOG_NDEBUG 0
 
 #include "ParameterManagerWrapper.h"
+#include <ParameterMgrFullConnector.h>
 #include <ParameterMgrPlatformConnector.h>
 #include <SelectionCriterionTypeInterface.h>
 #include <SelectionCriterionInterface.h>
 #include <media/convert.h>
 #include <algorithm>
 #include <cutils/bitops.h>
-#include <cutils/config_utils.h>
 #include <cutils/misc.h>
 #include <fstream>
 #include <limits>
@@ -64,31 +64,10 @@
 namespace audio_policy {
 
 const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
-    "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
+    "/etc/parameter-framework/ParameterFrameworkConfigurationCap.xml";
 const char *const ParameterManagerWrapper::mPolicyPfwVendorConfFileName =
     "/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
 
-static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
-static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
-static const char *const gPhoneStateCriterionName = "TelephonyMode";
-static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
-static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
-    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
-    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
-    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
-    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
-    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
-    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
-    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
-    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
-};
-
 template <>
 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
 template <>
@@ -100,9 +79,9 @@
 {
     // Connector
     if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
-        mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
+        mPfwConnector = new CParameterMgrFullConnector(mPolicyPfwVendorConfFileName);
     } else {
-        mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
+        mPfwConnector = new CParameterMgrFullConnector(mPolicyPfwDefaultConfFileName);
     }
 
     // Logger
@@ -130,13 +109,13 @@
               std::get<2>(pair).c_str(), name.c_str());
         criterionType->addValuePair(std::get<0>(pair), std::get<2>(pair), error);
 
-        if (name == gOutputDeviceCriterionName) {
+        if (name == capEngineConfig::gOutputDeviceCriterionName) {
             ALOGV("%s: Adding mOutputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
                   __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
             audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
             mOutputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
         }
-        if (name == gInputDeviceCriterionName) {
+        if (name == capEngineConfig::gInputDeviceCriterionName) {
             ALOGV("%s: Adding mInputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
                   __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
             audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
@@ -207,10 +186,11 @@
 
 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
 {
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gPhoneStateCriterionName);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -223,10 +203,11 @@
 
 audio_mode_t ParameterManagerWrapper::getPhoneState() const
 {
-    const ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
+    const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gPhoneStateCriterionName);
         return AUDIO_MODE_NORMAL;
     }
     return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -240,10 +221,11 @@
         return BAD_VALUE;
     }
 
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gForceUseCriterionTag[usage]);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -260,10 +242,11 @@
     if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
         return AUDIO_POLICY_FORCE_NONE;
     }
-    const ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+    const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gForceUseCriterionTag[usage]);
         return AUDIO_POLICY_FORCE_NONE;
     }
     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -281,8 +264,8 @@
         audio_devices_t type, const std::string &address, audio_policy_dev_state_t state)
 {
     std::string criterionName = audio_is_output_device(type) ?
-                gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
-
+            capEngineConfig::gOutputDeviceAddressCriterionName :
+            capEngineConfig::gInputDeviceAddressCriterionName;
     ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
           state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
     ISelectionCriterionInterface *criterion =
@@ -311,12 +294,12 @@
     return NO_ERROR;
 }
 
-status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types)
-{
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
+status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types) {
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gInputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __func__, gInputDeviceCriterionName);
+        ALOGE("%s: no criterion found for %s", __func__,
+              capEngineConfig::gInputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
@@ -324,12 +307,12 @@
     return NO_ERROR;
 }
 
-status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types)
-{
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
+status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types) {
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gOutputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __func__, gOutputDeviceCriterionName);
+        ALOGE("%s: no criterion found for %s", __func__,
+              capEngineConfig::gOutputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
@@ -344,21 +327,15 @@
 
 uint64_t ParameterManagerWrapper::convertDeviceTypeToCriterionValue(audio_devices_t type) const {
     bool isOut = audio_is_output_devices(type);
-    uint32_t typeMask = isOut ? type : (type & ~AUDIO_DEVICE_BIT_IN);
-
     const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
-    // Only multibit devices need adaptation.
-    if (popcount(typeMask) > 1) {
-        const auto &adapter = adapters.find(type);
-        if (adapter != adapters.end()) {
-            ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
-                  adapter->second);
-            return adapter->second;
-        }
-        ALOGE("%s: failed to find map for multibit device %d", __func__, type);
-        return 0;
+    const auto &adapter = adapters.find(type);
+    if (adapter != adapters.end()) {
+        ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
+              adapter->second);
+        return adapter->second;
     }
-    return typeMask;
+    ALOGE("%s: failed to find map for multibit device %d", __func__, type);
+    return 0;
 }
 
 uint64_t ParameterManagerWrapper::convertDeviceTypesToCriterionValue(
@@ -382,5 +359,88 @@
     return deviceTypes;
 }
 
+void ParameterManagerWrapper::createDomain(const std::string &domain)
+{
+    std::string error;
+    bool ret = mPfwConnector->createDomain(domain, error);
+    if (!ret) {
+        ALOGD("%s: failed to create domain %s (error=%s)", __func__, domain.c_str(),
+        error.c_str());
+    }
+}
+
+void ParameterManagerWrapper::addConfigurableElementToDomain(const std::string &domain,
+        const std::string &elementPath)
+{
+    std::string error;
+    bool ret = mPfwConnector->addConfigurableElementToDomain(domain, elementPath, error);
+    ALOGE_IF(!ret, "%s: failed to add parameter %s for domain %s (error=%s)",
+              __func__, elementPath.c_str(), domain.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::createConfiguration(const std::string &domain,
+        const std::string &configurationName)
+{
+    std::string error;
+    bool ret = mPfwConnector->createConfiguration(domain, configurationName, error);
+    ALOGE_IF(!ret, "%s: failed to create configuration %s for domain %s (error=%s)",
+              __func__, configurationName.c_str(), domain.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::setApplicationRule(
+        const std::string &domain, const std::string &configurationName, const std::string &rule)
+{
+    std::string error;
+    bool ret = mPfwConnector->setApplicationRule(domain, configurationName, rule, error);
+    ALOGE_IF(!ret, "%s: failed to set rule %s for domain %s and configuration %s (error=%s)",
+              __func__, rule.c_str(), domain.c_str(), configurationName.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::accessConfigurationValue(const std::string &domain,
+        const std::string &configurationName, const std::string &elementPath,
+        std::string &value)
+{
+    std::string error;
+    bool ret = mPfwConnector->accessConfigurationValue(domain, configurationName, elementPath,
+            value, /*set=*/ true, error);
+    ALOGE_IF(!ret, "%s: failed to set value %s for parameter %s on domain %s and configuration %s "
+          "(error=%s)", __func__, value.c_str(), elementPath.c_str(),  domain.c_str(),
+          configurationName.c_str(), error.c_str());
+}
+
+status_t ParameterManagerWrapper::setConfiguration(
+        const android::capEngineConfig::ParsingResult& capSettings)
+{
+    if (!isStarted()) {
+        return NO_INIT;
+    }
+    std::string error;
+    if (!mPfwConnector->setTuningMode(/* bOn= */ true, error)) {
+        ALOGD("%s: failed to set Tuning Mode error=%s", __FUNCTION__, error.c_str());
+        return DEAD_OBJECT;
+    }
+    for (auto &domain: capSettings.parsedConfig->capConfigurableDomains) {
+        createDomain(domain.name);
+        for (const auto &configurableElementValue : domain.settings[0].configurableElementValues) {
+            addConfigurableElementToDomain(domain.name,
+                    configurableElementValue.configurableElement.path);
+        }
+        for (const auto &configuration : domain.configurations) {
+            createConfiguration(domain.name, configuration.name);
+            setApplicationRule(domain.name, configuration.name, configuration.rule);
+        }
+        for (const auto &setting : domain.settings) {
+            for (const auto &configurableElementValue : setting.configurableElementValues) {
+                std::string value = configurableElementValue.value;
+                accessConfigurationValue(domain.name, setting.configurationName,
+                        configurableElementValue.configurableElement.path, value);
+            }
+
+        }
+    }
+    mPfwConnector->setTuningMode(/* bOn= */ false, error);
+    return OK;
+}
+
 } // namespace audio_policy
 } // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index fa4ae1e..0c45a60 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <CapEngineConfig.h>
 #include <media/AudioContainers.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
@@ -27,7 +28,7 @@
 #include <string>
 #include <vector>
 
-class CParameterMgrPlatformConnector;
+class CParameterMgrFullConnector;
 class ISelectionCriterionInterface;
 struct cnode;
 
@@ -59,6 +60,9 @@
      */
     status_t start(std::string &error);
 
+    status_t setConfiguration(const android::capEngineConfig::ParsingResult& capSettings);
+
+
     /**
      * The following API wrap policy action to criteria
      */
@@ -148,6 +152,14 @@
             uint64_t criterionValue, bool isOut) const;
 
 private:
+    void createDomain(const std::string &domain);
+    void addConfigurableElementToDomain(const std::string &domain, const std::string &elementPath);
+    void createConfiguration(const std::string &domain, const std::string &configurationName);
+    void setApplicationRule(const std::string &domain, const std::string &configurationName,
+            const std::string &rule);
+    void accessConfigurationValue(const std::string &domain, const std::string &configurationName,
+                                  const std::string &elementPath, std::string &value);
+
     /**
      * Apply the configuration of the platform on the policy parameter manager.
      * Once all the criteria have been set, the client of the platform state must call
@@ -206,7 +218,7 @@
 
     Criteria mPolicyCriteria; /**< Policy Criterion Map. */
 
-    CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
+    CParameterMgrFullConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
     ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
 
 
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 2c2f90d..deab0d7 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -50,7 +50,7 @@
         { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
         { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
         { "STRATEGY_REROUTING", STRATEGY_REROUTING },
-        { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
+        { "STRATEGY_PATCH", STRATEGY_PATCH }, // boiler to manage stream patch volume
         { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
     };
     return legacyStrategy;
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 878bca9..3d20c6f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -28,20 +28,6 @@
 namespace audio_policy
 {
 
-enum legacy_strategy {
-    STRATEGY_NONE = -1,
-    STRATEGY_MEDIA,
-    STRATEGY_PHONE,
-    STRATEGY_SONIFICATION,
-    STRATEGY_SONIFICATION_RESPECTFUL,
-    STRATEGY_DTMF,
-    STRATEGY_ENFORCED_AUDIBLE,
-    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
-    STRATEGY_ACCESSIBILITY,
-    STRATEGY_REROUTING,
-    STRATEGY_CALL_ASSISTANT,
-};
-
 class Engine : public EngineBase
 {
 public:
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 5e8bf34..e6e7c33 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -191,9 +191,7 @@
     media::AudioPolicyConfig apmConfig;
     if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
         auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
-        LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
-                AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
-                "Only default engine is currently supported with the AIDL HAL");
+        ALOGD("%s loading APM engine %s", __func__, config->getEngineLibraryNameSuffix().c_str());
         apm = new AudioPolicyManager(config,
                 loadApmEngineLibraryAndCreateEngine(
                         config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),