Mediaplayer: acquire the wake-lock synchronously am: 0913cb17a0 am: 5b426ac13e

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/23516263

Change-Id: I80cf4a7c753a20f689a9d13ceb3204d76893c46c
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 37f6457..302e250 100644
--- a/Android.bp
+++ b/Android.bp
@@ -102,3 +102,27 @@
         },
     },
 }
+
+aidl_interface {
+    name: "av-audio-types-aidl",
+    unstable: true,
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        "aidl/android/media/audio/IHalAdapterVendorExtension.aidl",
+    ],
+    imports: [
+        "android.hardware.audio.core-V1",
+    ],
+    backend: {
+        // The C++ backend is disabled transitively due to use of FMQ by the audio core HAL.
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
+}
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1f7083b..62cf827 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -12,3 +12,4 @@
                media/libmediatranscoding/
                services/mediatranscoding/
                media/libaudioclient/tests/
+               media/libaudiohal/tests/
diff --git a/aidl/android/media/audio/IHalAdapterVendorExtension.aidl b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
new file mode 100644
index 0000000..b7a7678
--- /dev/null
+++ b/aidl/android/media/audio/IHalAdapterVendorExtension.aidl
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2023 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 android.media.audio;
+
+import android.hardware.audio.core.VendorParameter;
+
+/**
+ * This interface is used by the HAL adapter of the Audio Server. Implementation
+ * is optional. Vendors may provide an implementation on the system_ext
+ * partition. The default instance of this interface, if provided, must be
+ * registered prior to the moment when the audio server connects to HAL modules.
+ *
+ * {@hide}
+ */
+interface IHalAdapterVendorExtension {
+    enum ParameterScope {
+        MODULE = 0,
+        STREAM = 1,
+    }
+
+    /**
+     * Parse raw parameter keys into vendor parameter ids.
+     *
+     * This method prepares arguments for a call to the 'getVendorParameters'
+     * method of an 'IModule' or an 'IStreamCommon' interface instance,
+     * depending on the provided scope.
+     *
+     * The client calls this method in order to prepare arguments for a call to
+     * the particular Core HAL interface. The result returned by the HAL is then
+     * processed using the 'processVendorParameters' method. It is not required
+     * to maintain a 1:1 correspondence between the provided raw keys and the
+     * elements of the parsed result. If the returned list is empty, the call of
+     * 'getVendorParameters' is skipped. The implementation can either ignore
+     * keys which it does not recognize, or throw an error. The latter is
+     * preferred as it can help in discovering malformed key names.
+     *
+     * @param scope The scope of all raw parameter keys.
+     * @param rawKeys Raw parameter keys, joined into a string using a semicolon
+     *                (';') as the delimiter.
+     * @return A list of vendor parameter IDs, see android.hardware.audio.core.VendorParameter.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw keys
+     *                             and prefers to signal an error.
+     */
+    @utf8InCpp String[] parseVendorParameterIds(
+            ParameterScope scope, in @utf8InCpp String rawKeys);
+
+    /**
+     * Parse raw parameter key-value pairs into vendor parameters.
+     *
+     * This method prepares arguments for a call to the 'setVendorParameters'
+     * method of an 'IModule' or an 'IStreamCommon' interface instance,
+     * depending on the provided scope.
+     *
+     * The vendor parameters returned using 'syncParameters' argument is then
+     * used to call the 'setVendorParameters' method with 'async = false', and
+     * 'asyncParameters' is used in a subsequent call to the same method, but
+     * with 'async = true'. It is not required to maintain a 1:1 correspondence
+     * between the provided key-value pairs and the elements of parsed
+     * results. If any of the returned lists of vendor parameters is empty, then
+     * the corresponding call is skipped. The implementation can either ignore
+     * keys which it does not recognize, and invalid values, or throw an
+     * error. The latter is preferred as it can help in discovering malformed
+     * key names and values.
+     *
+     * @param scope The scope of all raw key-value pairs.
+     * @param rawKeys Raw key-value pairs, separated by the "equals" sign ('='),
+     *                joined into a string using a semicolon (';') as the delimiter.
+     * @param syncParameters A list of vendor parameters to be set synchronously.
+     * @param asyncParameters A list of vendor parameters to be set asynchronously.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse raw key-value
+     *                             pairs and prefers to signal an error.
+     */
+    void parseVendorParameters(
+            ParameterScope scope, in @utf8InCpp String rawKeysAndValues,
+            out VendorParameter[] syncParameters, out VendorParameter[] asyncParameters);
+
+    /**
+     * Parse raw value of the parameter for BT A2DP reconfiguration.
+     *
+     * This method may return any number of vendor parameters (including zero)
+     * which will be passed to the 'IBluetoothA2dp.reconfigureOffload' method.
+     *
+     * @param rawValue An unparsed value of the legacy parameter.
+     * @return A list of vendor parameters.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value.
+     */
+    VendorParameter[] parseBluetoothA2dpReconfigureOffload(in @utf8InCpp String rawValue);
+
+    /**
+     * Parse raw value of the parameter for BT LE reconfiguration.
+     *
+     * This method may return any number of vendor parameters (including zero)
+     * which will be passed to the 'IBluetoothLe.reconfigureOffload' method.
+     *
+     * @param rawValue An unparsed value of the legacy parameter.
+     * @return A list of vendor parameters.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not parse the raw value.
+     */
+    VendorParameter[] parseBluetoothLeReconfigureOffload(in @utf8InCpp String rawValue);
+
+    /**
+     * Process vendor parameters returned by the Audio Core HAL.
+     *
+     * This processes the result returned from a call to the
+     * 'getVendorParameters' method of an 'IModule' or an 'IStreamCommon'
+     * interface instance, depending on the provided scope.
+     *
+     * See 'parseVendorParameterIds' method for the flow description.  It is not
+     * required to maintain a 1:1 correspondence between the elements of the
+     * provided list and the emitted key-value pairs. The returned string with
+     * raw key-value pairs is passed back to the framework.
+     *
+     * @param scope The scope of vendor parameters.
+     * @param parameters Vendor parameters, see android.hardware.audio.core.VendorParameter.
+     * @return Key-value pairs, separated by the "equals" sign ('='),
+     *         joined into a string using a semicolon (';') as the delimiter.
+     * @throws EX_ILLEGAL_ARGUMENT If the implementation can not emit raw key-value
+     *                             pairs and prefers to signal an error.
+     */
+    @utf8InCpp String processVendorParameters(
+            ParameterScope scope, in VendorParameter[] parameters);
+}
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 3b06245..4d3f9bd 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -18,6 +18,7 @@
 
 #include <algorithm>
 #include <map>
+#include <sstream>
 #include <utility>
 #include <vector>
 
@@ -50,6 +51,7 @@
 using ::android::status_t;
 using ::android::base::unexpected;
 
+using media::audio::common::AudioAttributes;
 using media::audio::common::AudioChannelLayout;
 using media::audio::common::AudioConfig;
 using media::audio::common::AudioConfigBase;
@@ -62,6 +64,7 @@
 using media::audio::common::AudioEncapsulationMetadataType;
 using media::audio::common::AudioEncapsulationMode;
 using media::audio::common::AudioEncapsulationType;
+using media::audio::common::AudioFlag;
 using media::audio::common::AudioFormatDescription;
 using media::audio::common::AudioFormatType;
 using media::audio::common::AudioGain;
@@ -95,6 +98,20 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Converters
 
+namespace {
+
+std::vector<std::string> splitString(const std::string& s, char separator) {
+    std::istringstream iss(s);
+    std::string t;
+    std::vector<std::string> result;
+    while (std::getline(iss, t, separator)) {
+        result.push_back(std::move(t));
+    }
+    return result;
+}
+
+}  // namespace
+
 ::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
     if (aidl.size() > maxSize - 1) {
         return BAD_VALUE;
@@ -262,12 +279,17 @@
 
         DEFINE_INPUT_LAYOUT(MONO),
         DEFINE_INPUT_LAYOUT(STEREO),
+        DEFINE_INPUT_LAYOUT(2POINT1),
         DEFINE_INPUT_LAYOUT(FRONT_BACK),
+        DEFINE_INPUT_LAYOUT(TRI),
+        DEFINE_INPUT_LAYOUT(3POINT1),
         // AUDIO_CHANNEL_IN_6 not supported
         DEFINE_INPUT_LAYOUT(2POINT0POINT2),
         DEFINE_INPUT_LAYOUT(2POINT1POINT2),
         DEFINE_INPUT_LAYOUT(3POINT0POINT2),
         DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+        DEFINE_INPUT_LAYOUT(QUAD),
+        DEFINE_INPUT_LAYOUT(PENTA),
         DEFINE_INPUT_LAYOUT(5POINT1)
 #undef DEFINE_INPUT_LAYOUT
     };
@@ -1799,6 +1821,156 @@
     return unexpected(BAD_VALUE);
 }
 
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(AudioFlag aidl) {
+    switch (aidl) {
+        case AudioFlag::NONE:
+            return AUDIO_FLAG_NONE;
+        case AudioFlag::AUDIBILITY_ENFORCED:
+            return AUDIO_FLAG_AUDIBILITY_ENFORCED;
+        // The is no AudioFlag::SECURE, see the comment in the AudioFlag.aidl
+        //  return AUDIO_FLAG_SECURE;
+        case AudioFlag::SCO:
+            return AUDIO_FLAG_SCO;
+        case AudioFlag::BEACON:
+            return AUDIO_FLAG_BEACON;
+        case AudioFlag::HW_AV_SYNC:
+            return AUDIO_FLAG_HW_AV_SYNC;
+        case AudioFlag::HW_HOTWORD:
+            return AUDIO_FLAG_HW_HOTWORD;
+        case AudioFlag::BYPASS_INTERRUPTION_POLICY:
+            return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
+        case AudioFlag::BYPASS_MUTE:
+            return AUDIO_FLAG_BYPASS_MUTE;
+        case AudioFlag::LOW_LATENCY:
+            return AUDIO_FLAG_LOW_LATENCY;
+        case AudioFlag::DEEP_BUFFER:
+            return AUDIO_FLAG_DEEP_BUFFER;
+        case AudioFlag::NO_MEDIA_PROJECTION:
+            return AUDIO_FLAG_NO_MEDIA_PROJECTION;
+        case AudioFlag::MUTE_HAPTIC:
+            return AUDIO_FLAG_MUTE_HAPTIC;
+        case AudioFlag::NO_SYSTEM_CAPTURE:
+            return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
+        case AudioFlag::CAPTURE_PRIVATE:
+            return AUDIO_FLAG_CAPTURE_PRIVATE;
+        case AudioFlag::CONTENT_SPATIALIZED:
+            return AUDIO_FLAG_CONTENT_SPATIALIZED;
+        case AudioFlag::NEVER_SPATIALIZE:
+            return AUDIO_FLAG_NEVER_SPATIALIZE;
+        case AudioFlag::CALL_REDIRECTION:
+            return AUDIO_FLAG_CALL_REDIRECTION;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
+    switch (legacy) {
+        case AUDIO_FLAG_NONE:
+            return AudioFlag::NONE;
+        case AUDIO_FLAG_AUDIBILITY_ENFORCED:
+            return AudioFlag::AUDIBILITY_ENFORCED;
+        case AUDIO_FLAG_SECURE:
+            return unexpected(BAD_VALUE);
+        case AUDIO_FLAG_SCO:
+            return AudioFlag::SCO;
+        case AUDIO_FLAG_BEACON:
+            return AudioFlag::BEACON;
+        case AUDIO_FLAG_HW_AV_SYNC:
+            return AudioFlag::HW_AV_SYNC;
+        case AUDIO_FLAG_HW_HOTWORD:
+            return AudioFlag::HW_HOTWORD;
+        case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
+            return AudioFlag::BYPASS_INTERRUPTION_POLICY;
+        case AUDIO_FLAG_BYPASS_MUTE:
+            return AudioFlag::BYPASS_MUTE;
+        case AUDIO_FLAG_LOW_LATENCY:
+            return AudioFlag::LOW_LATENCY;
+        case AUDIO_FLAG_DEEP_BUFFER:
+            return AudioFlag::DEEP_BUFFER;
+        case AUDIO_FLAG_NO_MEDIA_PROJECTION:
+            return AudioFlag::NO_MEDIA_PROJECTION;
+        case AUDIO_FLAG_MUTE_HAPTIC:
+            return AudioFlag::MUTE_HAPTIC;
+        case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
+            return AudioFlag::NO_SYSTEM_CAPTURE;
+        case AUDIO_FLAG_CAPTURE_PRIVATE:
+            return AudioFlag::CAPTURE_PRIVATE;
+        case AUDIO_FLAG_CONTENT_SPATIALIZED:
+            return AudioFlag::CONTENT_SPATIALIZED;
+        case AUDIO_FLAG_NEVER_SPATIALIZE:
+            return AudioFlag::NEVER_SPATIALIZE;
+        case AUDIO_FLAG_CALL_REDIRECTION:
+            return AudioFlag::CALL_REDIRECTION;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
+    return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, AudioFlag>(
+            aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_bitmask<AudioFlag>,
+            enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
+    return convertBitmask<int32_t, audio_flags_mask_t, AudioFlag, audio_flags_mask_t>(
+            legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
+            indexToEnum_bitmask<audio_flags_mask_t>,
+            enumToMask_bitmask<int32_t, AudioFlag>);
+}
+
+ConversionResult<std::string>
+aidl2legacy_AudioTags_string(const std::vector<std::string>& aidl) {
+    std::ostringstream tagsBuffer;
+    bool hasValue = false;
+    for (const auto& tag : aidl) {
+        if (hasValue) {
+            tagsBuffer << AUDIO_ATTRIBUTES_TAGS_SEPARATOR;
+        }
+        if (strchr(tag.c_str(), AUDIO_ATTRIBUTES_TAGS_SEPARATOR) == nullptr) {
+            tagsBuffer << tag;
+            hasValue = true;
+        } else {
+            ALOGE("Tag is ill-formed: \"%s\"", tag.c_str());
+            return unexpected(BAD_VALUE);
+        }
+    }
+    return tagsBuffer.str();
+}
+
+ConversionResult<std::vector<std::string>>
+legacy2aidl_string_AudioTags(const std::string& legacy) {
+    return splitString(legacy, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+}
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributes_audio_attributes_t(const AudioAttributes& aidl) {
+    audio_attributes_t legacy;
+    legacy.content_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
+    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+    legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
+    auto tagsString = VALUE_OR_RETURN(aidl2legacy_AudioTags_string(aidl.tags));
+    RETURN_IF_ERROR(aidl2legacy_string(tagsString, legacy.tags, sizeof(legacy.tags)));
+    return legacy;
+}
+
+ConversionResult<AudioAttributes>
+legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy) {
+    AudioAttributes aidl;
+    aidl.contentType = VALUE_OR_RETURN(
+            legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
+    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+    aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source));
+    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
+    auto tagsString = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
+    aidl.tags = VALUE_OR_RETURN(legacy2aidl_string_AudioTags(tagsString));
+    return aidl;
+}
 
 ConversionResult<audio_encapsulation_mode_t>
 aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
diff --git a/media/audioaidlconversion/AidlConversionNdkCpp.cpp b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
index c64a074..ecd2e5e 100644
--- a/media/audioaidlconversion/AidlConversionNdkCpp.cpp
+++ b/media/audioaidlconversion/AidlConversionNdkCpp.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <algorithm>
+#include <regex>
 #include <type_traits>
 
 #define LOG_TAG "AidlConversionNdkCpp"
@@ -34,6 +35,24 @@
 
 namespace {
 
+bool isVendorExtension(const std::string& s) {
+    // Per definition in AudioAttributes.aidl and {Playback|Record}TrackMetadata.aidl
+    static const std::regex vendorExtension("VX_[A-Z0-9]{3,}_[_A-Z0-9]+");
+    return std::regex_match(s.begin(), s.end(), vendorExtension);
+}
+
+inline bool isNotVendorExtension(const std::string& s) { return !isVendorExtension(s); }
+
+void filterOutNonVendorTagsInPlace(std::vector<std::string>& tags) {
+    if (std::find_if(tags.begin(), tags.end(), isNotVendorExtension) == tags.end()) {
+        return;
+    }
+    std::vector<std::string> temp;
+    temp.reserve(tags.size());
+    std::copy_if(tags.begin(), tags.end(), std::back_inserter(temp), isVendorExtension);
+    tags = std::move(temp);
+}
+
 // cpp2ndk and ndk2cpp are universal converters which work for any type,
 // however they are not the most efficient way to convert due to extra
 // marshaling / unmarshaling step.
@@ -99,12 +118,15 @@
 
 }  // namespace
 
-#define GENERATE_CONVERTERS(packageName, className)                     \
-    ConversionResult<::aidl::packageName::className> cpp2ndk_##className( \
+#define GENERATE_CONVERTERS(packageName, className) \
+    GENERATE_CONVERTERS_IMPL(packageName, _, className)
+
+#define GENERATE_CONVERTERS_IMPL(packageName, prefix, className)        \
+    ConversionResult<::aidl::packageName::className> cpp2ndk##prefix##className( \
             const ::packageName::className& cpp) {                      \
         return cpp2ndk<::aidl::packageName::className>(cpp);            \
     }                                                                   \
-    ConversionResult<::packageName::className> ndk2cpp_##className(     \
+    ConversionResult<::packageName::className> ndk2cpp##prefix##className( \
             const ::aidl::packageName::className& ndk) {                \
         return ndk2cpp<::packageName::className>(ndk);                  \
     }
@@ -120,10 +142,46 @@
 }
 
 GENERATE_CONVERTERS(android::media::audio::common, AudioFormatDescription);
-GENERATE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
+GENERATE_CONVERTERS_IMPL(android::media::audio::common, _Impl_, AudioHalEngineConfig);
 GENERATE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
 GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
 GENERATE_ENUM_CONVERTERS(android::media::audio::common, AudioMode);
 GENERATE_CONVERTERS(android::media::audio::common, AudioPort);
 
+namespace {
+
+// Filter out all AudioAttributes tags that do not conform to the vendor extension pattern.
+template<typename T>
+void filterOutNonVendorTags(T& audioHalEngineConfig) {
+    for (auto& strategy : audioHalEngineConfig.productStrategies) {
+        for (auto& group : strategy.attributesGroups) {
+            for (auto& attr : group.attributes) {
+                filterOutNonVendorTagsInPlace(attr.tags);
+            }
+        }
+    }
+}
+
+}  // namespace
+
+ConversionResult<::aidl::android::media::audio::common::AudioHalEngineConfig>
+cpp2ndk_AudioHalEngineConfig(const ::android::media::audio::common::AudioHalEngineConfig& cpp) {
+    auto conv = cpp2ndk_Impl_AudioHalEngineConfig(cpp);
+    if (conv.ok()) {
+        filterOutNonVendorTags(conv.value());
+    }
+    return conv;
+}
+
+ConversionResult<::android::media::audio::common::AudioHalEngineConfig>
+ndk2cpp_AudioHalEngineConfig(
+        const ::aidl::android::media::audio::common::AudioHalEngineConfig& ndk) {
+    auto conv = ndk2cpp_Impl_AudioHalEngineConfig(ndk);
+    if (conv.ok()) {
+        filterOutNonVendorTags(conv.value());
+    }
+    return conv;
+}
+
+
 }  // namespace android
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
index 903b88a..216bc12 100644
--- a/media/audioaidlconversion/TEST_MAPPING
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -1,6 +1,7 @@
 {
   "presubmit": [
     {
+      "name": "audio_aidl_conversion_tests",
       "name": "audio_aidl_ndk_conversion_tests",
       "name": "audio_aidl_ndk_cpp_conversion_tests"
     }
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index bc9d4d5..7268464 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -37,6 +37,7 @@
 #define PREFIX(f) <f>
 #endif
 
+#include PREFIX(android/media/audio/common/AudioAttributes.h)
 #include PREFIX(android/media/audio/common/AudioChannelLayout.h)
 #include PREFIX(android/media/audio/common/AudioConfig.h)
 #include PREFIX(android/media/audio/common/AudioConfigBase.h)
@@ -46,6 +47,7 @@
 #include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
 #include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
 #include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFlag.h)
 #include PREFIX(android/media/audio/common/AudioFormatDescription.h)
 #include PREFIX(android/media/audio/common/AudioGain.h)
 #include PREFIX(android/media/audio/common/AudioGainConfig.h)
@@ -355,6 +357,26 @@
 ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
         audio_usage_t legacy);
 
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_AudioFlag_audio_flags_mask_t(media::audio::common::AudioFlag aidl);
+ConversionResult<media::audio::common::AudioFlag>
+legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
+
+ConversionResult<audio_flags_mask_t>
+aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
+ConversionResult<int32_t>
+legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
+
+ConversionResult<std::string>
+aidl2legacy_AudioTags_string(const std::vector<std::string>& aidl);
+ConversionResult<std::vector<std::string>>
+legacy2aidl_string_AudioTags(const std::string& legacy);
+
+ConversionResult<audio_attributes_t>
+aidl2legacy_AudioAttributes_audio_attributes_t(const media::audio::common::AudioAttributes& aidl);
+ConversionResult<media::audio::common::AudioAttributes>
+legacy2aidl_audio_attributes_t_AudioAttributes(const audio_attributes_t& legacy);
+
 ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
         const media::audio::common::AudioUuid &aidl);
 ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index f49f681..656d76a 100644
--- a/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -119,6 +119,20 @@
 }
 
 /**
+ * A generic template that helps convert containers of convertible types without
+ * using an intermediate container.
+ */
+template<typename InputContainer, typename OutputContainer, typename Func>
+::android::status_t convertContainer(const InputContainer& input, OutputContainer* output,
+        const Func& itemConversion) {
+    auto ins = std::inserter(*output, output->begin());
+    for (const auto& item : input) {
+        *ins = VALUE_OR_RETURN_STATUS(itemConversion(item));
+    }
+    return ::android::OK;
+}
+
+/**
  * A generic template that helps convert containers of convertible types.
  */
 template<typename OutputContainer, typename InputContainer, typename Func>
@@ -208,6 +222,34 @@
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Utilities for handling bitmasks.
+// Some AIDL enums are specified using bit indices, for example:
+//   `AidlEnum { FOO = 0, BAR = 1, BAZ = 2' }`
+// while corresponding legacy types universally uses actual bitmasks, for example:
+//   `enum legacy_enum_t { LEGACY_FOO = 1 << 0, LEGACY_BAR = 1 << 1, LEGACY_BAZ = 1 << 2 }`
+// There is also the third type used to store the resulting mask, which is combined
+// from individual bits. In AIDL this is typically an int (`int32_t`), in legacy types this
+// is often the enum type itself (although, strictly this is not correct since masks are not
+// declared as part of the enum type). The bit index value always has an integer type.
+//
+// `indexToEnum_index` constructs an instance of the enum from an index,
+// for example `AidlEnum::BAR` from `1`.
+// `indexToEnum_bitmask` produces a corresponding legacy bitmask enum instance,
+// for example, `LEGACY_BAR` (`2`) from `1`.
+// `enumToMask_bitmask` simply casts an enum type to a bitmask type.
+// `enumToMask_index` creates a mask from an enum type which specifies an index.
+//
+// All these functions can be plugged into `convertBitmask`. For example, to implement
+// conversion from `AidlEnum` to `legacy_enum_t`, with a mask stored in `int32_t`,
+// the following call needs to be made:
+//   convertBitmask<legacy_enum_t /*DestMask*/, int32_t /*SrcMask*/,
+//                  legacy_enum_t /*DestEnum*/, AidlEnum /*SrcEnum*/>(
+//     maskField /*int32_t*/, aidl2legacy_AidlEnum_legacy_enum_t /*enumConversion*/,
+//     indexToEnum_index<AidlEnum> /*srcIndexToEnum*/,
+//     enumToMask_bitmask<legacy_enum_t, legacy_enum_t> /*destEnumToMask*/)
+//
+// The only extra function needed is for mapping between corresponding enum values
+// of the AidlEnum and the legacy_enum_t. Note that the mapping is between values
+// of enums, for example, `AidlEnum::BAZ` maps to `LEGACY_BAZ` and vice versa.
 
 template<typename Enum>
 Enum indexToEnum_index(int index) {
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
index c505e60..60727b4 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
@@ -19,6 +19,7 @@
 
 #include <gtest/gtest.h>
 
+#include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionNdk.h>
 
 namespace {
@@ -89,3 +90,48 @@
     ASSERT_EQ(1, convBack.value().tags.size());
     EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
 }
+
+class AudioTagsRoundTripTest : public testing::TestWithParam<std::vector<std::string>>
+{
+};
+TEST_P(AudioTagsRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto& initial = GetParam();
+    auto conv = aidl2legacy_AudioTags_string(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_string_AudioTags(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioTagsRoundTrip, AudioTagsRoundTripTest,
+        testing::Values(std::vector<std::string>{},
+                std::vector<std::string>{"VX_GOOGLE_41"},
+                std::vector<std::string>{"VX_GOOGLE_41", "VX_GOOGLE_42"}));
+
+TEST(AudioTags, NonVendorTagsAllowed) {
+    const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+    const std::vector<std::string> initial{"random_string", "VX_GOOGLE_42"};
+    auto conv = aidl2legacy_AudioTags_string(initial);
+    ASSERT_TRUE(conv.ok());
+    EXPECT_EQ("random_string" + separator + "VX_GOOGLE_42", conv.value());
+}
+
+TEST(AudioTags, IllFormedAidlTag) {
+    const std::string separator(1, AUDIO_ATTRIBUTES_TAGS_SEPARATOR);
+    {
+        const std::vector<std::string> initial{"VX_GOOGLE" + separator + "42", "VX_GOOGLE_42"};
+        auto conv = aidl2legacy_AudioTags_string(initial);
+        if (conv.ok()) {
+            EXPECT_EQ("VX_GOOGLE_42", conv.value());
+        }
+        // Failing this conversion is also OK. The result depends on whether the conversion
+        // only passes through vendor tags.
+    }
+    {
+        const std::vector<std::string> initial{
+            "random_string", "random" + separator + "string", "VX_GOOGLE_42"};
+        auto conv = aidl2legacy_AudioTags_string(initial);
+        if (conv.ok()) {
+            EXPECT_EQ("VX_GOOGLE_42", conv.value());
+        }
+    }
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
index 735a14b..206c35b 100644
--- a/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_cpp_conversion_tests.cpp
@@ -125,3 +125,12 @@
 INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip, AudioFormatDescriptionRoundTripTest,
         testing::Values(make_AFD_Invalid(), make_AFD_Default(), make_AFD_Pcm16Bit(),
                 make_AFD_Bitstream(), make_AFD_Encap(), make_AFD_Encap_with_Enc()));
+
+TEST(AudioPortRoundTripTest, Ndk2Cpp2Ndk) {
+    const AudioPort initial;
+    auto conv = ndk2cpp_AudioPort(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = cpp2ndk_AudioPort(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index b32667e..bd10e44 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -480,129 +480,6 @@
     return aidl;
 }
 
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
-    switch (aidl) {
-        case media::AudioFlag::AUDIBILITY_ENFORCED:
-            return AUDIO_FLAG_AUDIBILITY_ENFORCED;
-        case media::AudioFlag::SECURE:
-            return AUDIO_FLAG_SECURE;
-        case media::AudioFlag::SCO:
-            return AUDIO_FLAG_SCO;
-        case media::AudioFlag::BEACON:
-            return AUDIO_FLAG_BEACON;
-        case media::AudioFlag::HW_AV_SYNC:
-            return AUDIO_FLAG_HW_AV_SYNC;
-        case media::AudioFlag::HW_HOTWORD:
-            return AUDIO_FLAG_HW_HOTWORD;
-        case media::AudioFlag::BYPASS_INTERRUPTION_POLICY:
-            return AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY;
-        case media::AudioFlag::BYPASS_MUTE:
-            return AUDIO_FLAG_BYPASS_MUTE;
-        case media::AudioFlag::LOW_LATENCY:
-            return AUDIO_FLAG_LOW_LATENCY;
-        case media::AudioFlag::DEEP_BUFFER:
-            return AUDIO_FLAG_DEEP_BUFFER;
-        case media::AudioFlag::NO_MEDIA_PROJECTION:
-            return AUDIO_FLAG_NO_MEDIA_PROJECTION;
-        case media::AudioFlag::MUTE_HAPTIC:
-            return AUDIO_FLAG_MUTE_HAPTIC;
-        case media::AudioFlag::NO_SYSTEM_CAPTURE:
-            return AUDIO_FLAG_NO_SYSTEM_CAPTURE;
-        case media::AudioFlag::CAPTURE_PRIVATE:
-            return AUDIO_FLAG_CAPTURE_PRIVATE;
-        case media::AudioFlag::CONTENT_SPATIALIZED:
-            return AUDIO_FLAG_CONTENT_SPATIALIZED;
-        case media::AudioFlag::NEVER_SPATIALIZE:
-            return AUDIO_FLAG_NEVER_SPATIALIZE;
-        case media::AudioFlag::CALL_REDIRECTION:
-            return AUDIO_FLAG_CALL_REDIRECTION;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioFlag>
-legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy) {
-    switch (legacy) {
-        case AUDIO_FLAG_NONE:
-            return unexpected(BAD_VALUE);
-        case AUDIO_FLAG_AUDIBILITY_ENFORCED:
-            return media::AudioFlag::AUDIBILITY_ENFORCED;
-        case AUDIO_FLAG_SECURE:
-            return media::AudioFlag::SECURE;
-        case AUDIO_FLAG_SCO:
-            return media::AudioFlag::SCO;
-        case AUDIO_FLAG_BEACON:
-            return media::AudioFlag::BEACON;
-        case AUDIO_FLAG_HW_AV_SYNC:
-            return media::AudioFlag::HW_AV_SYNC;
-        case AUDIO_FLAG_HW_HOTWORD:
-            return media::AudioFlag::HW_HOTWORD;
-        case AUDIO_FLAG_BYPASS_INTERRUPTION_POLICY:
-            return media::AudioFlag::BYPASS_INTERRUPTION_POLICY;
-        case AUDIO_FLAG_BYPASS_MUTE:
-            return media::AudioFlag::BYPASS_MUTE;
-        case AUDIO_FLAG_LOW_LATENCY:
-            return media::AudioFlag::LOW_LATENCY;
-        case AUDIO_FLAG_DEEP_BUFFER:
-            return media::AudioFlag::DEEP_BUFFER;
-        case AUDIO_FLAG_NO_MEDIA_PROJECTION:
-            return media::AudioFlag::NO_MEDIA_PROJECTION;
-        case AUDIO_FLAG_MUTE_HAPTIC:
-            return media::AudioFlag::MUTE_HAPTIC;
-        case AUDIO_FLAG_NO_SYSTEM_CAPTURE:
-            return media::AudioFlag::NO_SYSTEM_CAPTURE;
-        case AUDIO_FLAG_CAPTURE_PRIVATE:
-            return media::AudioFlag::CAPTURE_PRIVATE;
-        case AUDIO_FLAG_CONTENT_SPATIALIZED:
-            return media::AudioFlag::CONTENT_SPATIALIZED;
-        case AUDIO_FLAG_NEVER_SPATIALIZE:
-            return media::AudioFlag::NEVER_SPATIALIZE;
-        case AUDIO_FLAG_CALL_REDIRECTION:
-            return media::AudioFlag::CALL_REDIRECTION;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl) {
-    return convertBitmask<audio_flags_mask_t, int32_t, audio_flags_mask_t, media::AudioFlag>(
-            aidl, aidl2legacy_AudioFlag_audio_flags_mask_t, indexToEnum_index<media::AudioFlag>,
-            enumToMask_bitmask<audio_flags_mask_t, audio_flags_mask_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy) {
-    return convertBitmask<int32_t, audio_flags_mask_t, media::AudioFlag, audio_flags_mask_t>(
-            legacy, legacy2aidl_audio_flags_mask_t_AudioFlag,
-            indexToEnum_bitmask<audio_flags_mask_t>,
-            enumToMask_index<int32_t, media::AudioFlag>);
-}
-
-ConversionResult<audio_attributes_t>
-aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl) {
-    audio_attributes_t legacy;
-    legacy.content_type = VALUE_OR_RETURN(
-            aidl2legacy_AudioContentType_audio_content_type_t(aidl.contentType));
-    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
-    legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
-    legacy.flags = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_flags_mask_t_mask(aidl.flags));
-    RETURN_IF_ERROR(aidl2legacy_string(aidl.tags, legacy.tags, sizeof(legacy.tags)));
-    return legacy;
-}
-
-ConversionResult<media::AudioAttributesInternal>
-legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy) {
-    media::AudioAttributesInternal aidl;
-    aidl.contentType = VALUE_OR_RETURN(
-            legacy2aidl_audio_content_type_t_AudioContentType(legacy.content_type));
-    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
-    aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source));
-    aidl.flags = VALUE_OR_RETURN(legacy2aidl_audio_flags_mask_t_int32_t_mask(legacy.flags));
-    aidl.tags = VALUE_OR_RETURN(legacy2aidl_string(legacy.tags, sizeof(legacy.tags)));
-    return aidl;
-}
-
 ConversionResult<sp<IMemory>>
 aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
     sp<IMemory> legacy;
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 7122af1..01e3d53 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -281,10 +281,8 @@
     double_loadable: true,
     local_include_dir: "aidl",
     srcs: [
-        "aidl/android/media/AudioAttributesInternal.aidl",
         "aidl/android/media/AudioClient.aidl",
         "aidl/android/media/AudioDirectMode.aidl",
-        "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainSys.aidl",
         "aidl/android/media/AudioHalVersion.aidl",
         "aidl/android/media/AudioHwModule.aidl",
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 4527e0f..7cec2e8 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1066,8 +1066,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return NO_INIT;
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
     int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
     AudioConfig configAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
@@ -1106,7 +1106,7 @@
     *isSpatialized = responseAidl.isSpatialized;
     *isBitPerfect = responseAidl.isBitPerfect;
     *attr = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(responseAidl.attr));
+            aidl2legacy_AudioAttributes_audio_attributes_t(responseAidl.attr));
 
     return OK;
 }
@@ -1171,8 +1171,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return NO_INIT;
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
     int32_t inputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(*input));
     int32_t riidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_unique_id_t_int32_t(riid));
     int32_t sessionAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_session_t_int32_t(session));
@@ -1293,8 +1293,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     int32_t indexAidl = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(index));
     AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
@@ -1308,8 +1308,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     AudioDeviceDescription deviceAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_devices_t_AudioDeviceDescription(device));
     int32_t indexAidl;
@@ -1323,8 +1323,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     int32_t indexAidl;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             aps->getMaxVolumeIndexForAttributes(attrAidl, &indexAidl)));
@@ -1336,8 +1336,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     int32_t indexAidl;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             aps->getMinVolumeIndexForAttributes(attrAidl, &indexAidl)));
@@ -1369,8 +1369,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal aaAidl = VALUE_OR_RETURN_STATUS(
-             legacy2aidl_audio_attributes_t_AudioAttributesInternal(aa));
+    media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+             legacy2aidl_audio_attributes_t_AudioAttributes(aa));
     std::vector<AudioDevice> retAidl;
     RETURN_STATUS_IF_ERROR(
             statusTFromBinderStatus(aps->getDevicesForAttributes(aaAidl, forVolume, &retAidl)));
@@ -1888,8 +1888,8 @@
 
     media::AudioPortConfigFw sourceAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_port_config_AudioPortConfigFw(*source));
-    media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attributes));
+    media::audio::common::AudioAttributes attributesAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attributes));
     int32_t portIdAidl;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             aps->startAudioSource(sourceAidl, attributesAidl, &portIdAidl)));
@@ -2175,8 +2175,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal aaAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(aa));
+    media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(aa));
     int32_t productStrategyAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2205,8 +2205,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesInternal aaAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(aa));
+    media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(aa));
     int32_t volumeGroupAidl;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             aps->getVolumeGroupFromAudioAttributes(aaAidl, fallbackOnDefault, &volumeGroupAidl)));
@@ -2411,8 +2411,8 @@
     audio_attributes_t attributes = attr != nullptr ? *attr : AUDIO_ATTRIBUTES_INITIALIZER;
     audio_config_t configuration = config != nullptr ? *config : AUDIO_CONFIG_INITIALIZER;
 
-    std::optional<media::AudioAttributesInternal> attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
+    std::optional<media::audio::common::AudioAttributes> attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
     std::optional<AudioConfig> configAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_config_t_AudioConfig(configuration, false /*isInput*/));
     std::vector<AudioDevice> devicesAidl = VALUE_OR_RETURN_STATUS(
@@ -2449,8 +2449,8 @@
         return PERMISSION_DENIED;
     }
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
     AudioConfig configAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
 
@@ -2473,8 +2473,8 @@
         return PERMISSION_DENIED;
     }
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
 
     std::vector<media::audio::common::AudioProfile> audioProfilesAidl;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2653,8 +2653,8 @@
         return PERMISSION_DENIED;
     }
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
     media::AudioMixerAttributesInternal mixerAttrAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_mixer_attributes_t_AudioMixerAttributesInternal(*mixerAttr));
     int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
@@ -2673,8 +2673,8 @@
         return PERMISSION_DENIED;
     }
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
     int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
     std::optional<media::AudioMixerAttributesInternal> _aidlReturn;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2696,8 +2696,8 @@
         return PERMISSION_DENIED;
     }
 
-    media::AudioAttributesInternal attrAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attr));
+    media::audio::common::AudioAttributes attrAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(*attr));
     int32_t uidAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(uid));
     int32_t portIdAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(portId));
     return statusTFromBinderStatus(
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index f01b653..359c140 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -178,8 +178,8 @@
     auto result = [&]() -> ConversionResult<bool> {
         media::audio::common::AudioConfigBase configAidl = VALUE_OR_RETURN(
                 legacy2aidl_audio_config_base_t_AudioConfigBase(config, false /*isInput*/));
-        media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN(
-                legacy2aidl_audio_attributes_t_AudioAttributesInternal(attributes));
+        media::audio::common::AudioAttributes attributesAidl = VALUE_OR_RETURN(
+                legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
         bool retAidl;
         RETURN_IF_ERROR(aidl_utils::statusTFromBinderStatus(
                 aps->isDirectOutputSupported(configAidl, attributesAidl, &retAidl)));
diff --git a/media/libaudioclient/AudioVolumeGroup.cpp b/media/libaudioclient/AudioVolumeGroup.cpp
index 978599e..c4ca5b9 100644
--- a/media/libaudioclient/AudioVolumeGroup.cpp
+++ b/media/libaudioclient/AudioVolumeGroup.cpp
@@ -49,9 +49,9 @@
     aidl.groupId = VALUE_OR_RETURN(legacy2aidl_volume_group_t_int32_t(legacy.getId()));
     aidl.name = legacy.getName();
     aidl.audioAttributes = VALUE_OR_RETURN(
-            convertContainer<std::vector<media::AudioAttributesInternal>>(
+            convertContainer<std::vector<media::audio::common::AudioAttributes>>(
                     legacy.getAudioAttributes(),
-                    legacy2aidl_audio_attributes_t_AudioAttributesInternal));
+                    legacy2aidl_audio_attributes_t_AudioAttributes));
     aidl.streams = VALUE_OR_RETURN(
             convertContainer<std::vector<AudioStreamType>>(legacy.getStreamTypes(),
             legacy2aidl_audio_stream_type_t_AudioStreamType));
@@ -65,7 +65,7 @@
             VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
             VALUE_OR_RETURN(convertContainer<AttributesVector>(
                     aidl.audioAttributes,
-                    aidl2legacy_AudioAttributesInternal_audio_attributes_t)),
+                    aidl2legacy_AudioAttributes_audio_attributes_t)),
             VALUE_OR_RETURN(convertContainer<StreamTypeVector>(
                     aidl.streams,
                     aidl2legacy_AudioStreamType_audio_stream_type_t))
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 7b33a00..7caaaaf 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -56,7 +56,7 @@
 
 ConversionResult<media::CreateTrackRequest> IAudioFlinger::CreateTrackInput::toAidl() const {
     media::CreateTrackRequest aidl;
-    aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     // Do not be mislead by 'Input'--this is an input to 'createTrack', which creates output tracks.
     aidl.config = VALUE_OR_RETURN(legacy2aidl_audio_config_t_AudioConfig(
                     config, false /*isInput*/));
@@ -77,7 +77,7 @@
 ConversionResult<IAudioFlinger::CreateTrackInput>
 IAudioFlinger::CreateTrackInput::fromAidl(const media::CreateTrackRequest& aidl) {
     IAudioFlinger::CreateTrackInput legacy;
-    legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+    legacy.attr = VALUE_OR_RETURN(aidl2legacy_AudioAttributes_audio_attributes_t(aidl.attr));
     // Do not be mislead by 'Input'--this is an input to 'createTrack', which creates output tracks.
     legacy.config = VALUE_OR_RETURN(
             aidl2legacy_AudioConfig_audio_config_t(aidl.config, false /*isInput*/));
@@ -153,7 +153,7 @@
 ConversionResult<media::CreateRecordRequest>
 IAudioFlinger::CreateRecordInput::toAidl() const {
     media::CreateRecordRequest aidl;
-    aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+    aidl.attr = VALUE_OR_RETURN(legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     aidl.config = VALUE_OR_RETURN(
             legacy2aidl_audio_config_base_t_AudioConfigBase(config, true /*isInput*/));
     aidl.clientInfo = VALUE_OR_RETURN(legacy2aidl_AudioClient_AudioClient(clientInfo));
@@ -174,7 +174,7 @@
         const media::CreateRecordRequest& aidl) {
     IAudioFlinger::CreateRecordInput legacy;
     legacy.attr = VALUE_OR_RETURN(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(aidl.attr));
+            aidl2legacy_AudioAttributes_audio_attributes_t(aidl.attr));
     legacy.config = VALUE_OR_RETURN(
             aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.config, true /*isInput*/));
     legacy.clientInfo = VALUE_OR_RETURN(aidl2legacy_AudioClient_AudioClient(aidl.clientInfo));
diff --git a/media/libaudioclient/VolumeGroupAttributes.cpp b/media/libaudioclient/VolumeGroupAttributes.cpp
index 530e73f..938e574 100644
--- a/media/libaudioclient/VolumeGroupAttributes.cpp
+++ b/media/libaudioclient/VolumeGroupAttributes.cpp
@@ -48,7 +48,7 @@
 legacy2aidl_VolumeGroupAttributes_AudioAttributesEx(const VolumeGroupAttributes& legacy) {
     media::AudioAttributesEx aidl;
     aidl.attributes = VALUE_OR_RETURN(
-            legacy2aidl_audio_attributes_t_AudioAttributesInternal(legacy.getAttributes()));
+            legacy2aidl_audio_attributes_t_AudioAttributes(legacy.getAttributes()));
     aidl.streamType = VALUE_OR_RETURN(
             legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.getStreamType()));
     aidl.groupId = VALUE_OR_RETURN(legacy2aidl_volume_group_t_int32_t(legacy.getGroupId()));
@@ -60,7 +60,7 @@
     return VolumeGroupAttributes(VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
                            VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
                                    aidl.streamType)),
-                           VALUE_OR_RETURN(aidl2legacy_AudioAttributesInternal_audio_attributes_t(
+                           VALUE_OR_RETURN(aidl2legacy_AudioAttributes_audio_attributes_t(
                                    aidl.attributes)));
 }
 
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
index 335866f..7827bdb 100644
--- a/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioAttributesEx.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
 import android.media.audio.common.AudioStreamType;
 
 /**
@@ -24,7 +24,7 @@
  * {@hide}
  */
 parcelable AudioAttributesEx {
-    AudioAttributesInternal attributes;
+    AudioAttributes attributes;
     AudioStreamType streamType;
     /** Interpreted as volume_group_t. */
     int groupId;
diff --git a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl b/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
deleted file mode 100644
index 2e74206..0000000
--- a/media/libaudioclient/aidl/android/media/AudioAttributesInternal.aidl
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2020 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 android.media;
-
-import android.media.audio.common.AudioContentType;
-import android.media.audio.common.AudioSource;
-import android.media.audio.common.AudioUsage;
-
-/**
- * The "Internal" suffix of this type name is to disambiguate it from the
- * android.media.AudioAttributes SDK type.
- * {@hide}
- */
-parcelable AudioAttributesInternal {
-    AudioContentType contentType;
-    AudioUsage usage;
-    AudioSource source;
-    // Bitmask, indexed by AudioFlag.
-    int flags;
-    @utf8InCpp String tags; /* UTF8 */
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioFlag.aidl b/media/libaudioclient/aidl/android/media/AudioFlag.aidl
deleted file mode 100644
index acf4e6d..0000000
--- a/media/libaudioclient/aidl/android/media/AudioFlag.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2020 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 android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioFlag {
-    AUDIBILITY_ENFORCED = 0,
-    SECURE = 1,
-    SCO = 2,
-    BEACON = 3,
-    HW_AV_SYNC = 4,
-    HW_HOTWORD = 5,
-    BYPASS_INTERRUPTION_POLICY = 6,
-    BYPASS_MUTE = 7,
-    LOW_LATENCY = 8,
-    DEEP_BUFFER = 9,
-    NO_MEDIA_PROJECTION = 10,
-    MUTE_HAPTIC = 11,
-    NO_SYSTEM_CAPTURE = 12,
-    CAPTURE_PRIVATE = 13,
-    CONTENT_SPATIALIZED = 14,
-    NEVER_SPATIALIZE = 15,
-    CALL_REDIRECTION = 16,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
index b95a1d3..424f8b8 100644
--- a/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioVolumeGroup.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
 import android.media.audio.common.AudioStreamType;
 
 /**
@@ -26,6 +26,6 @@
     /** Interpreted as volume_group_t. */
     int groupId;
     @utf8InCpp String name;
-    AudioAttributesInternal[] audioAttributes;
+    AudioAttributes[] audioAttributes;
     AudioStreamType[] streams;
 }
diff --git a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
index b938a3e..57e8f42 100644
--- a/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateRecordRequest.aidl
@@ -16,8 +16,8 @@
 
 package android.media;
 
-import android.media.AudioAttributesInternal;
 import android.media.AudioClient;
+import android.media.audio.common.AudioAttributes;
 import android.media.audio.common.AudioConfigBase;
 
 /**
@@ -28,7 +28,7 @@
  * {@hide}
  */
 parcelable CreateRecordRequest {
-    AudioAttributesInternal attr;
+    AudioAttributes attr;
     AudioConfigBase config;
     AudioClient clientInfo;
     /** Interpreted as audio_unique_id_t. */
diff --git a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
index 212221e..24e6a6c 100644
--- a/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/CreateTrackRequest.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.AudioAttributesInternal;
+import android.media.audio.common.AudioAttributes;
 import android.media.AudioClient;
 import android.media.IAudioTrackCallback;
 import android.media.SharedFileRegion;
@@ -30,7 +30,7 @@
  * {@hide}
  */
 parcelable CreateTrackRequest {
-    AudioAttributesInternal attr;
+    AudioAttributes attr;
     AudioConfig config;
     AudioClient clientInfo;
     @nullable SharedFileRegion sharedBuffer;
diff --git a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
index 9d44bb0..b814b85 100644
--- a/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
+++ b/media/libaudioclient/aidl/android/media/GetOutputForAttrResponse.aidl
@@ -16,9 +16,9 @@
 
 package android.media;
 
+import android.media.audio.common.AudioAttributes;
 import android.media.audio.common.AudioConfigBase;
 import android.media.audio.common.AudioStreamType;
-import android.media.AudioAttributesInternal;
 /**
  * {@hide}
  */
@@ -38,5 +38,5 @@
     AudioConfigBase configBase;
     boolean isBitPerfect;
     /** The corrected audio attributes. **/
-    AudioAttributesInternal attr;
+    AudioAttributes attr;
 }
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 90ede8b..3e9b27f 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -18,8 +18,6 @@
 
 import android.content.AttributionSourceState;
 
-import android.media.AudioAttributesEx;
-import android.media.AudioAttributesInternal;
 import android.media.AudioDirectMode;
 import android.media.AudioMix;
 import android.media.AudioMixerAttributesInternal;
@@ -43,6 +41,7 @@
 import android.media.ICaptureStateListener;
 import android.media.INativeSpatializerCallback;
 import android.media.SoundTriggerSession;
+import android.media.audio.common.AudioAttributes;
 import android.media.audio.common.AudioConfig;
 import android.media.audio.common.AudioConfigBase;
 import android.media.audio.common.AudioDevice;
@@ -85,7 +84,7 @@
 
     int /* audio_io_handle_t */ getOutput(AudioStreamType stream);
 
-    GetOutputForAttrResponse getOutputForAttr(in AudioAttributesInternal attr,
+    GetOutputForAttrResponse getOutputForAttr(in AudioAttributes attr,
                                               int /* audio_session_t */ session,
                                               in AttributionSourceState attributionSource,
                                               in AudioConfig config,
@@ -98,7 +97,7 @@
 
     void releaseOutput(int /* audio_port_handle_t */ portId);
 
-    GetInputForAttrResponse getInputForAttr(in AudioAttributesInternal attr,
+    GetInputForAttrResponse getInputForAttr(in AudioAttributes attr,
                                             int /* audio_io_handle_t */ input,
                                             int /* audio_unique_id_t */ riid,
                                             int /* audio_session_t */ session,
@@ -125,20 +124,20 @@
     int getStreamVolumeIndex(AudioStreamType stream,
                              in AudioDeviceDescription device);
 
-    void setVolumeIndexForAttributes(in AudioAttributesInternal attr,
+    void setVolumeIndexForAttributes(in AudioAttributes attr,
                                      in AudioDeviceDescription device,
                                      int index);
 
-    int getVolumeIndexForAttributes(in AudioAttributesInternal attr,
+    int getVolumeIndexForAttributes(in AudioAttributes attr,
                                     in AudioDeviceDescription device);
 
-    int getMaxVolumeIndexForAttributes(in AudioAttributesInternal attr);
+    int getMaxVolumeIndexForAttributes(in AudioAttributes attr);
 
-    int getMinVolumeIndexForAttributes(in AudioAttributesInternal attr);
+    int getMinVolumeIndexForAttributes(in AudioAttributes attr);
 
     int /* product_strategy_t */ getStrategyForStream(AudioStreamType stream);
 
-    AudioDevice[] getDevicesForAttributes(in AudioAttributesInternal attr, boolean forVolume);
+    AudioDevice[] getDevicesForAttributes(in AudioAttributes attr, boolean forVolume);
 
     int /* audio_io_handle_t */ getOutputForEffect(in EffectDescriptor desc);
 
@@ -200,7 +199,7 @@
      * Check if direct playback is possible for given format, sample rate, channel mask and flags.
      */
     boolean isDirectOutputSupported(in AudioConfigBase config,
-                                    in AudioAttributesInternal attributes);
+                                    in AudioAttributes attributes);
 
     /**
      * List currently attached audio ports and their attributes. Returns the generation.
@@ -272,7 +271,7 @@
     void removeUserIdDeviceAffinities(int userId);
 
     int /* audio_port_handle_t */ startAudioSource(in AudioPortConfigFw source,
-                                                   in AudioAttributesInternal attributes);
+                                                   in AudioAttributes attributes);
 
     void stopAudioSource(int /* audio_port_handle_t */ portId);
 
@@ -333,10 +332,10 @@
 
     AudioProductStrategy[] listAudioProductStrategies();
     int /* product_strategy_t */ getProductStrategyFromAudioAttributes(
-            in AudioAttributesInternal aa, boolean fallbackOnDefault);
+            in AudioAttributes aa, boolean fallbackOnDefault);
 
     AudioVolumeGroup[] listAudioVolumeGroups();
-    int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributesInternal aa,
+    int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributes aa,
                                                                boolean fallbackOnDefault);
 
     void setRttEnabled(boolean enabled);
@@ -397,21 +396,21 @@
      * supported criteria. For instance, supplying no argument will tell if spatialization is
      * supported or not in general.
      */
-    boolean canBeSpatialized(in @nullable AudioAttributesInternal attr,
+    boolean canBeSpatialized(in @nullable AudioAttributes attr,
                              in @nullable AudioConfig config,
                              in AudioDevice[] devices);
 
     /**
      * Query how the direct playback is currently supported on the device.
      */
-    AudioDirectMode getDirectPlaybackSupport(in AudioAttributesInternal attr,
+    AudioDirectMode getDirectPlaybackSupport(in AudioAttributes attr,
                                               in AudioConfig config);
 
     /**
      * Query audio profiles available for direct playback on the current output device(s)
      * for the specified audio attributes.
      */
-    AudioProfile[] getDirectProfilesForAttributes(in AudioAttributesInternal attr);
+    AudioProfile[] getDirectProfilesForAttributes(in AudioAttributes attr);
 
     /**
      * Return a list of AudioMixerAttributes that can be used to set preferred mixer attributes
@@ -435,7 +434,7 @@
      *            playback is routed to the given device.
      * @param mixerAttr the preferred mixer attributes.
      */
-    void setPreferredMixerAttributes(in AudioAttributesInternal attr,
+    void setPreferredMixerAttributes(in AudioAttributes attr,
                                      int /* audio_port_handle_t */ portId,
                                      int /* uid_t */ uid,
                                      in AudioMixerAttributesInternal mixerAttr);
@@ -449,7 +448,7 @@
      * @param portId the port id of the device to be routed.
      */
     @nullable AudioMixerAttributesInternal getPreferredMixerAttributes(
-            in AudioAttributesInternal attr,
+            in AudioAttributes attr,
             int /* audio_port_handle_t */ portId);
 
     /**
@@ -462,7 +461,7 @@
      *            preferred mixer attributes. The preferred mixer attributes will only be cleared
      *            if the uid is the same as the owner of current preferred mixer attributes.
      */
-    void clearPreferredMixerAttributes(in AudioAttributesInternal attr,
+    void clearPreferredMixerAttributes(in AudioAttributes attr,
                                        int /* audio_port_handle_t */ portId,
                                        int /* uid_t */ uid);
 
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index b0d48b7..10f6d4a 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -21,10 +21,8 @@
 
 #include <system/audio.h>
 
-#include <android/media/AudioAttributesInternal.h>
 #include <android/media/AudioClient.h>
 #include <android/media/AudioDirectMode.h>
-#include <android/media/AudioFlag.h>
 #include <android/media/AudioIoConfigEvent.h>
 #include <android/media/AudioIoDescriptor.h>
 #include <android/media/AudioPortFw.h>
@@ -105,21 +103,6 @@
 ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
         const AudioClient& legacy);
 
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
-ConversionResult<media::AudioFlag>
-legacy2aidl_audio_flags_mask_t_AudioFlag(audio_flags_mask_t legacy);
-
-ConversionResult<audio_flags_mask_t>
-aidl2legacy_int32_t_audio_flags_mask_t_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_flags_mask_t_int32_t_mask(audio_flags_mask_t legacy);
-
-ConversionResult<audio_attributes_t>
-aidl2legacy_AudioAttributesInternal_audio_attributes_t(const media::AudioAttributesInternal& aidl);
-ConversionResult<media::AudioAttributesInternal>
-legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
-
 ConversionResult<sp<IMemory>>
 aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
 ConversionResult<media::SharedFileRegion>
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 0d12f9d..976a532 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -94,6 +94,11 @@
             AudioChannelLayout::LAYOUT_STEREO);
 }
 
+AudioChannelLayout make_ACL_Tri() {
+    return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+            AudioChannelLayout::LAYOUT_TRI);
+}
+
 AudioChannelLayout make_ACL_LayoutArbitrary() {
     return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
             // Use channels that exist both for input and output,
@@ -311,8 +316,8 @@
         AudioChannelLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
         testing::Combine(
                 testing::Values(AudioChannelLayout{}, make_ACL_Invalid(), make_ACL_Stereo(),
-                                make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
-                                make_ACL_ChannelIndexArbitrary(),
+                                make_ACL_Tri(), make_ACL_LayoutArbitrary(),
+                                make_ACL_ChannelIndex2(), make_ACL_ChannelIndexArbitrary(),
                                 AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
                                         AudioChannelLayout::CHANNEL_FRONT_LEFT),
                                 AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
diff --git a/media/libaudioclient/tests/audioclient_serialization_tests.cpp b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
index d1e3d16..707b9b3 100644
--- a/media/libaudioclient/tests/audioclient_serialization_tests.cpp
+++ b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
@@ -103,7 +103,7 @@
     attr.usage = kUsages[rand() % kUsages.size()];
     attr.source = kInputSources[rand() % kInputSources.size()];
     // attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)]
-    attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3fff);
+    attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3ffd);  // exclude AUDIO_FLAG_SECURE
     sprintf(attr.tags, "%s",
             CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str());
 }
@@ -119,6 +119,7 @@
 TEST_F(SerializationTest, AudioProductStrategyBinderization) {
     for (int j = 0; j < 512; j++) {
         const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)};
+        SCOPED_TRACE(name);
         std::vector<VolumeGroupAttributes> volumeGroupAttrVector;
         for (auto i = 0; i < 16; i++) {
             audio_attributes_t attributes;
@@ -132,20 +133,19 @@
         AudioProductStrategy aps{name, volumeGroupAttrVector, psId};
 
         Parcel p;
-        EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p)) << name;
+        EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p));
 
         AudioProductStrategy apsCopy;
         p.setDataPosition(0);
-        EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p)) << name;
-        EXPECT_EQ(apsCopy.getName(), name) << name;
-        EXPECT_EQ(apsCopy.getId(), psId) << name;
+        EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p));
+        EXPECT_EQ(apsCopy.getName(), name);
+        EXPECT_EQ(apsCopy.getId(), psId);
         auto avec = apsCopy.getVolumeGroupAttributes();
-        EXPECT_EQ(avec.size(), volumeGroupAttrVector.size()) << name;
-        for (int i = 0; i < volumeGroupAttrVector.size(); i++) {
-            EXPECT_EQ(avec[i].getGroupId(), volumeGroupAttrVector[i].getGroupId()) << name;
-            EXPECT_EQ(avec[i].getStreamType(), volumeGroupAttrVector[i].getStreamType()) << name;
-            EXPECT_TRUE(avec[i].getAttributes() == volumeGroupAttrVector[i].getAttributes())
-                    << name;
+        EXPECT_EQ(avec.size(), volumeGroupAttrVector.size());
+        for (int i = 0; i < std::min(avec.size(), volumeGroupAttrVector.size()); i++) {
+            EXPECT_EQ(avec[i].getGroupId(), volumeGroupAttrVector[i].getGroupId());
+            EXPECT_EQ(avec[i].getStreamType(), volumeGroupAttrVector[i].getStreamType());
+            EXPECT_TRUE(avec[i].getAttributes() == volumeGroupAttrVector[i].getAttributes());
         }
     }
 }
diff --git a/media/libaudiohal/TEST_MAPPING b/media/libaudiohal/TEST_MAPPING
index 5d3fb0a..90f481b 100644
--- a/media/libaudiohal/TEST_MAPPING
+++ b/media/libaudiohal/TEST_MAPPING
@@ -16,6 +16,9 @@
           "include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic_TestAAudioBasic_TestBasic_LOW_LATENCY__OUTPUT"
         }
       ]
+    },
+    {
+      "name": "CoreAudioHalAidlTest"
     }
   ]
 }
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 09e70eb..1689365 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -245,20 +245,48 @@
     ]
 }
 
-cc_library_shared {
-    name: "libaudiohal@aidl",
+cc_defaults {
+    name: "libaudiohal_aidl_default",
     defaults: [
-        "libaudiohal_default",
         "latest_android_hardware_audio_common_ndk_shared",
         "latest_android_hardware_audio_core_ndk_shared",
         "latest_android_hardware_audio_core_sounddose_ndk_shared",
         "latest_android_hardware_audio_effect_ndk_shared",
         "latest_android_media_audio_common_types_ndk_shared",
     ],
+    shared_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "av-audio-types-aidl-ndk",
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudio_aidl_conversion_common_ndk",
+        "libaudio_aidl_conversion_common_ndk_cpp",
+        "libaudio_aidl_conversion_core_ndk",
+        "libaudio_aidl_conversion_effect_ndk",
+        "libaudioaidlcommon",
+        "libbinder_ndk",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+        "libeffectsconfig_headers",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_CPP_NDK",
+    ],
+}
+
+cc_library_shared {
+    name: "libaudiohal@aidl",
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_aidl_default",
+    ],
     srcs: [
-        "DeviceHalAidl.cpp",
         "DevicesFactoryHalEntry.cpp",
-        "DevicesFactoryHalAidl.cpp",
         "EffectConversionHelperAidl.cpp",
         "EffectBufferHalAidl.cpp",
         "EffectHalAidl.cpp",
@@ -280,32 +308,18 @@
         "effectsAidlConversion/AidlConversionVisualizer.cpp",
         "EffectsFactoryHalAidl.cpp",
         "EffectsFactoryHalEntry.cpp",
+        ":audio_effectproxy_src_files",
+        ":core_audio_hal_aidl_src_files",
+    ],
+}
+
+filegroup {
+    name: "core_audio_hal_aidl_src_files",
+    srcs: [
+        "ConversionHelperAidl.cpp",
+        "DeviceHalAidl.cpp",
+        "DevicesFactoryHalAidl.cpp",
         "StreamHalAidl.cpp",
-        ":audio_effectproxy_src_files"
-    ],
-    static_libs: [
-        "android.hardware.common-V2-ndk",
-        "android.hardware.common.fmq-V1-ndk",
-    ],
-    shared_libs: [
-        "libaudio_aidl_conversion_common_cpp",
-        "libaudio_aidl_conversion_common_ndk",
-        "libaudio_aidl_conversion_common_ndk_cpp",
-        "libaudio_aidl_conversion_core_ndk",
-        "libaudio_aidl_conversion_effect_ndk",
-        "libaudioaidlcommon",
-        "libbinder_ndk",
-    ],
-    header_libs: [
-        "libaudio_system_headers",
-        "libeffectsconfig_headers",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wthread-safety",
-        "-DBACKEND_CPP_NDK",
     ],
 }
 
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.cpp b/media/libaudiohal/impl/ConversionHelperAidl.cpp
new file mode 100644
index 0000000..7197bf2
--- /dev/null
+++ b/media/libaudiohal/impl/ConversionHelperAidl.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ConversionHelperAidl"
+
+#include <memory>
+
+#include <media/AidlConversionUtil.h>
+#include <utils/Log.h>
+
+#include "ConversionHelperAidl.h"
+
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::core::VendorParameter;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
+
+namespace android {
+
+status_t parseAndGetVendorParameters(
+        std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameterKeys,
+        String8* values) {
+    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
+    if (parameterKeys.size() == 0) return OK;
+    const String8 rawKeys = parameterKeys.keysToString();
+    if (vendorExt == nullptr) {
+        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
+        return OK;
+    }
+
+    std::vector<std::string> parameterIds;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
+                            ParameterScope(recipient.index()),
+                            std::string(rawKeys.c_str()), &parameterIds)));
+    if (parameterIds.empty()) return OK;
+
+    std::vector<VendorParameter> parameters;
+    if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+        auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->getVendorParameters(
+                                parameterIds, &parameters)));
+    } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+        auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->getVendorParameters(
+                                parameterIds, &parameters)));
+    } else {
+        LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
+                __func__, recipient.index());
+    }
+    if (!parameters.empty()) {
+        std::string vendorParameters;
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->processVendorParameters(
+                                ParameterScope(recipient.index()),
+                                parameters, &vendorParameters)));
+        // Re-parse the vendor-provided string to ensure that it is correct.
+        AudioParameter reparse(String8(vendorParameters.c_str()));
+        if (reparse.size() != 0) {
+            if (!values->empty()) {
+                values->append(";");
+            }
+            values->append(reparse.toString().c_str());
+        }
+    }
+    return OK;
+}
+
+status_t parseAndSetVendorParameters(
+        std::shared_ptr<IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameters) {
+    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
+    if (parameters.size() == 0) return OK;
+    const String8 rawKeysAndValues = parameters.toString();
+    if (vendorExt == nullptr) {
+        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
+        return OK;
+    }
+
+    std::vector<VendorParameter> syncParameters, asyncParameters;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
+                            ParameterScope(recipient.index()),
+                            std::string(rawKeysAndValues.c_str()),
+                            &syncParameters, &asyncParameters)));
+    if (recipient.index() == static_cast<int>(ParameterScope::MODULE)) {
+        auto module = std::get<static_cast<int>(ParameterScope::MODULE)>(recipient);
+        if (!syncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
+                                    syncParameters, false /*async*/)));
+        }
+        if (!asyncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(module->setVendorParameters(
+                                    asyncParameters, true /*async*/)));
+        }
+    } else if (recipient.index() == static_cast<int>(ParameterScope::STREAM)) {
+        auto stream = std::get<static_cast<int>(ParameterScope::STREAM)>(recipient);
+        if (!syncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
+                                    syncParameters, false /*async*/)));
+        }
+        if (!asyncParameters.empty()) {
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(stream->setVendorParameters(
+                                    asyncParameters, true /*async*/)));
+        }
+    } else {
+        LOG_ALWAYS_FATAL("%s: unexpected recipient variant index: %zu",
+                __func__, recipient.index());
+    }
+    return OK;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
index 5534d13..0fadd9c 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -18,8 +18,12 @@
 
 #include <string>
 #include <string_view>
+#include <variant>
 #include <vector>
 
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/IStreamCommon.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <android-base/expected.h>
 #include <error/Result.h>
 #include <media/AudioParameter.h>
@@ -74,4 +78,18 @@
     return false;
 }
 
+// Must use the same order of elements as IHalAdapterVendorExtension::ParameterScope.
+using VendorParametersRecipient = std::variant<
+        std::shared_ptr<::aidl::android::hardware::audio::core::IModule>,
+        std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>>;
+status_t parseAndGetVendorParameters(
+        std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameterKeys,
+        String8* values);
+status_t parseAndSetVendorParameters(
+        std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> vendorExt,
+        const VendorParametersRecipient& recipient,
+        const AudioParameter& parameters);
+
 }  // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 3125e311..b1b7e00 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -62,6 +62,7 @@
 using aidl::android::media::audio::common::Int;
 using aidl::android::media::audio::common::MicrophoneDynamicInfo;
 using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
 using aidl::android::hardware::audio::common::getFrameSizeInBytes;
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::isDefaultAudioFormat;
@@ -76,6 +77,7 @@
 using aidl::android::hardware::audio::core::ITelephony;
 using aidl::android::hardware::audio::core::ModuleDebug;
 using aidl::android::hardware::audio::core::StreamDescriptor;
+using aidl::android::hardware::audio::core::VendorParameter;
 
 namespace android {
 
@@ -125,9 +127,10 @@
 
 }  // namespace
 
-DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module)
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
+                             const std::shared_ptr<IHalAdapterVendorExtension>& vext)
         : ConversionHelperAidl("DeviceHalAidl"),
-          mInstance(instance), mModule(module),
+          mInstance(instance), mModule(module), mVendorExt(vext),
           mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
           mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
           mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
@@ -135,11 +138,8 @@
 }
 
 status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
-    auto convertAudioPortFromMap = [](const Ports::value_type& pair) {
-        return ndk2cpp_AudioPort(pair.second);
-    };
-    return ::aidl::android::convertRange(mPorts.begin(), mPorts.end(), ports->begin(),
-            convertAudioPortFromMap);
+    return ::aidl::android::convertContainer(mPorts, ports,
+            [](const Ports::value_type& pair) { return ndk2cpp_AudioPort(pair.second); });
 }
 
 status_t DeviceHalAidl::getAudioRoutes(std::vector<media::AudioRoute> *routes) {
@@ -289,19 +289,24 @@
     if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
         ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
     }
-
-    ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: \"%s\"",
-            __func__, parameters.toString().c_str());
-    return OK;
+    if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
+        ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
+    }
+    return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
 }
 
-status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
     TIME_CHECK();
-    // FIXME(b/278976019): Support keyReconfigA2dpSupported via vendor plugin
-    values->clear();
     if (!mModule) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    if (values == nullptr) {
+        return BAD_VALUE;
+    }
+    AudioParameter parameterKeys(keys), result;
+    if (status_t status = filterAndRetrieveBtA2dpParameters(parameterKeys, &result); status != OK) {
+        ALOGW("%s: filtering or retrieving BT A2DP parameters failed: %d", __func__, status);
+    }
+    *values = result.toString();
+    return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
 }
 
 namespace {
@@ -571,7 +576,7 @@
         return NO_INIT;
     }
     *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
-            std::move(ret.stream), this /*callbackBroker*/);
+            std::move(ret.stream), mVendorExt, this /*callbackBroker*/);
     mStreams.insert(std::pair(*outStream, aidlPatch.id));
     void* cbCookie = (*outStream).get();
     {
@@ -632,7 +637,7 @@
         return NO_INIT;
     }
     *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
-            std::move(ret.stream), this /*micInfoProvider*/);
+            std::move(ret.stream), mVendorExt, this /*micInfoProvider*/);
     mStreams.insert(std::pair(*inStream, aidlPatch.id));
     cleanups.disarmAll();
     return OK;
@@ -1112,9 +1117,23 @@
     return OK;
 }
 
+status_t DeviceHalAidl::filterAndRetrieveBtA2dpParameters(
+        AudioParameter &keys, AudioParameter *result) {
+    TIME_CHECK();
+    if (String8 key = String8(AudioParameter::keyReconfigA2dpSupported); keys.containsKey(key)) {
+        keys.remove(key);
+        bool supports;
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                        mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
+        result->addInt(key, supports ? 1 : 0);
+    }
+    return OK;
+}
+
 status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &parameters) {
     TIME_CHECK();
     std::optional<bool> a2dpEnabled;
+    std::optional<std::vector<VendorParameter>> reconfigureOffload;
     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                     parameters, String8(AudioParameter::keyBtA2dpSuspended),
                     [&a2dpEnabled](const String8& trueOrFalse) {
@@ -1129,10 +1148,27 @@
                                 AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
                         return BAD_VALUE;
                     }));
-    // FIXME(b/278976019): Support keyReconfigA2dp via vendor plugin
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyReconfigA2dp),
+                    [&](const String8& value) -> status_t {
+                        if (mVendorExt != nullptr) {
+                            std::vector<VendorParameter> result;
+                            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                                    mVendorExt->parseBluetoothA2dpReconfigureOffload(
+                                            std::string(value.c_str()), &result)));
+                            reconfigureOffload = std::move(result);
+                        } else {
+                            reconfigureOffload = std::vector<VendorParameter>();
+                        }
+                        return OK;
+                    }));
     if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
         return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
     }
+    if (mBluetoothA2dp != nullptr && reconfigureOffload.has_value()) {
+        return statusTFromBinderStatus(mBluetoothA2dp->reconfigureOffload(
+                        reconfigureOffload.value()));
+    }
     return OK;
 }
 
@@ -1256,6 +1292,44 @@
     return OK;
 }
 
+status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
+    TIME_CHECK();
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyScreenState),
+                    [&](const String8& onOrOff) -> status_t {
+                        std::optional<bool> isTurnedOn;
+                        if (onOrOff == AudioParameter::valueOn) {
+                            isTurnedOn = true;
+                        } else if (onOrOff == AudioParameter::valueOff) {
+                            isTurnedOn = false;
+                        }
+                        if (!isTurnedOn.has_value()) {
+                            ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                    AudioParameter::keyScreenState, onOrOff.c_str());
+                            return BAD_VALUE;
+                        }
+                        return statusTFromBinderStatus(
+                                mModule->updateScreenState(isTurnedOn.value()));
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                    parameters, String8(AudioParameter::keyScreenRotation),
+            [&](int rotationDegrees) -> status_t {
+                IModule::ScreenRotation rotation;
+                switch (rotationDegrees) {
+                    case 0: rotation = IModule::ScreenRotation::DEG_0; break;
+                    case 90: rotation = IModule::ScreenRotation::DEG_90; break;
+                    case 180: rotation = IModule::ScreenRotation::DEG_180; break;
+                    case 270: rotation = IModule::ScreenRotation::DEG_270; break;
+                    default:
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value %d",
+                                AudioParameter::keyScreenRotation, rotationDegrees);
+                        return BAD_VALUE;
+                }
+                return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
+            }));
+    return OK;
+}
+
 status_t DeviceHalAidl::findOrCreatePatch(
         const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
     std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index 37d800b..03afbb7 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -20,6 +20,7 @@
 #include <set>
 #include <vector>
 
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <aidl/android/hardware/audio/core/BpModule.h>
 #include <aidl/android/hardware/audio/core/sounddose/BpSoundDose.h>
 #include <android-base/thread_annotations.h>
@@ -203,7 +204,8 @@
     // Must not be constructed directly by clients.
     DeviceHalAidl(
             const std::string& instance,
-            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module);
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext);
 
     ~DeviceHalAidl() override = default;
 
@@ -214,10 +216,12 @@
     status_t createOrUpdatePortConfig(
             const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
             PortConfigs::iterator* result, bool *created);
+    status_t filterAndRetrieveBtA2dpParameters(AudioParameter &keys, AudioParameter *result);
     status_t filterAndUpdateBtA2dpParameters(AudioParameter &parameters);
     status_t filterAndUpdateBtHfpParameters(AudioParameter &parameters);
     status_t filterAndUpdateBtLeParameters(AudioParameter &parameters);
     status_t filterAndUpdateBtScoParameters(AudioParameter &parameters);
+    status_t filterAndUpdateScreenParameters(AudioParameter &parameters);
     status_t findOrCreatePatch(
         const std::set<int32_t>& sourcePortConfigIds,
         const std::set<int32_t>& sinkPortConfigIds,
@@ -291,6 +295,7 @@
 
     const std::string mInstance;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+    const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
     const std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony> mTelephony;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth> mBluetooth;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp> mBluetoothA2dp;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
index 8345cd2..f00b1a0 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -34,7 +34,8 @@
 using aidl::android::hardware::audio::core::IModule;
 using aidl::android::hardware::audio::core::SurroundSoundConfig;
 using aidl::android::media::audio::common::AudioHalEngineConfig;
-using ::android::detail::AudioHalVersionInfo;
+using aidl::android::media::audio::IHalAdapterVendorExtension;
+using android::detail::AudioHalVersionInfo;
 
 namespace android {
 
@@ -83,25 +84,16 @@
     if (name == nullptr || device == nullptr) {
         return BAD_VALUE;
     }
-
-    // FIXME: Remove this call and the check for the supported module names
-    // after implementing retrieval of module names on the framework side.
-    // Currently it is still using the legacy XML config.
-    std::vector<std::string> deviceNames;
-    if (status_t status = getDeviceNames(&deviceNames); status != OK) {
-        return status;
-    }
     std::shared_ptr<IModule> service;
-    if (std::find(deviceNames.begin(), deviceNames.end(), name) != deviceNames.end()) {
-        if (strcmp(name, "primary") == 0) name = "default";
-        auto serviceName = std::string(IModule::descriptor) + "/" + name;
-        service = IModule::fromBinder(
-                ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
-        ALOGE_IF(service == nullptr, "%s fromBinder %s failed", __func__, serviceName.c_str());
+    if (strcmp(name, "primary") == 0) name = "default";
+    auto serviceName = std::string(IModule::descriptor) + "/" + name;
+    service = IModule::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+    if (service == nullptr) {
+        ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
+        return NO_INIT;
     }
-    // If the service is a nullptr, the device object will not be really functional,
-    // but will not crash either.
-    *device = sp<DeviceHalAidl>::make(name, service);
+    *device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
     return OK;
 }
 
@@ -163,6 +155,20 @@
     return OK;
 }
 
+std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
+    if (!mVendorExt.has_value()) {
+        auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
+        if (AServiceManager_isDeclared(serviceName.c_str())) {
+            mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
+                    IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
+                                    AServiceManager_waitForService(serviceName.c_str()))));
+        } else {
+            mVendorExt = nullptr;
+        }
+    }
+    return mVendorExt.value();
+}
+
 // Main entry-point to the shared library.
 extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
     auto serviceName = std::string(IConfig::descriptor) + "/default";
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
index 21957bc..97e3796 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalAidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <aidl/android/hardware/audio/core/IConfig.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <utils/RefBase.h>
 
@@ -46,6 +47,11 @@
 
   private:
     const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
+    std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
+            mVendorExt;
+
+    std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension();
+
     ~DevicesFactoryHalAidl() = default;
 };
 
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index d1044dc..c84f80f 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -43,6 +43,7 @@
 using ::aidl::android::hardware::audio::core::StreamDescriptor;
 using ::aidl::android::hardware::audio::core::MmapBufferDescriptor;
 using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using ::aidl::android::media::audio::IHalAdapterVendorExtension;
 
 namespace android {
 
@@ -73,12 +74,14 @@
 StreamHalAidl::StreamHalAidl(
         std::string_view className, bool isInput, const audio_config& config,
         int32_t nominalLatency, StreamContextAidl&& context,
-        const std::shared_ptr<IStreamCommon>& stream)
+        const std::shared_ptr<IStreamCommon>& stream,
+        const std::shared_ptr<IHalAdapterVendorExtension>& vext)
         : ConversionHelperAidl(className),
           mIsInput(isInput),
           mConfig(configToBase(config)),
           mContext(std::move(context)),
-          mStream(stream) {
+          mStream(stream),
+          mVendorExt(vext) {
     {
         std::lock_guard l(mLock);
         mLastReply.latencyMs = nominalLatency;
@@ -125,7 +128,6 @@
 status_t StreamHalAidl::setParameters(const String8& kvPairs) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-
     AudioParameter parameters(kvPairs);
     ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
 
@@ -134,18 +136,18 @@
             [&](int hwAvSyncId) {
                 return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
             }));
-
-    ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s",
-            __func__, parameters.toString().c_str());
-    return OK;
+    return parseAndSetVendorParameters(mVendorExt, mStream, parameters);
 }
 
 status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
-    values->clear();
-    // AIDL HAL doesn't support getParameters API.
-    return INVALID_OPERATION;
+    if (!mStream) return NO_INIT;
+    if (values == nullptr) {
+        return BAD_VALUE;
+    }
+    AudioParameter parameterKeys(keys), result;
+    *values = result.toString();
+    return parseAndGetVendorParameters(mVendorExt, mStream, parameterKeys, values);
 }
 
 status_t StreamHalAidl::getFrameSize(size_t *size) {
@@ -533,9 +535,11 @@
 
 StreamOutHalAidl::StreamOutHalAidl(
         const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
-        const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+        const std::shared_ptr<IStreamOut>& stream,
+        const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+        const sp<CallbackBroker>& callbackBroker)
         : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
-                std::move(context), getStreamCommon(stream)),
+                std::move(context), getStreamCommon(stream), vext),
           mStream(stream), mCallbackBroker(callbackBroker) {
     // Initialize the offload metadata
     mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
@@ -861,9 +865,11 @@
 
 StreamInHalAidl::StreamInHalAidl(
         const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
-        const std::shared_ptr<IStreamIn>& stream, const sp<MicrophoneInfoProvider>& micInfoProvider)
+        const std::shared_ptr<IStreamIn>& stream,
+        const std::shared_ptr<IHalAdapterVendorExtension>& vext,
+        const sp<MicrophoneInfoProvider>& micInfoProvider)
         : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
-                std::move(context), getStreamCommon(stream)),
+                std::move(context), getStreamCommon(stream), vext),
           mStream(stream), mMicInfoProvider(micInfoProvider) {}
 
 status_t StreamInHalAidl::setGain(float gain) {
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 75a1dd9..3b369bd 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -26,9 +26,11 @@
 #include <aidl/android/hardware/audio/core/BpStreamIn.h>
 #include <aidl/android/hardware/audio/core/BpStreamOut.h>
 #include <aidl/android/hardware/audio/core/MmapBufferDescriptor.h>
+#include <aidl/android/media/audio/IHalAdapterVendorExtension.h>
 #include <fmq/AidlMessageQueue.h>
 #include <media/audiohal/EffectHalInterface.h>
 #include <media/audiohal/StreamHalInterface.h>
+#include <media/AidlConversionUtil.h>
 #include <media/AudioParameter.h>
 
 #include "ConversionHelperAidl.h"
@@ -48,7 +50,7 @@
     typedef AidlMessageQueue<int8_t,
             ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
 
-    explicit StreamContextAidl(
+    StreamContextAidl(
             ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
             bool isAsynchronous)
         : mFrameSizeBytes(descriptor.frameSizeBytes),
@@ -185,6 +187,9 @@
     status_t legacyReleaseAudioPatch() override;
 
   protected:
+    // For tests.
+    friend class sp<StreamHalAidl>;
+
     template<class T>
     static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
             const std::shared_ptr<T>& stream);
@@ -195,7 +200,8 @@
             const audio_config& config,
             int32_t nominalLatency,
             StreamContextAidl&& context,
-            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext);
 
     ~StreamHalAidl() override;
 
@@ -247,6 +253,7 @@
             ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
 
     const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
+    const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;
     std::mutex mLock;
     ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
     // mStreamPowerLog is used for audio signal power logging.
@@ -349,6 +356,7 @@
     StreamOutHalAidl(
             const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
             const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext,
             const sp<CallbackBroker>& callbackBroker);
 
     ~StreamOutHalAidl() override;
@@ -401,6 +409,7 @@
     StreamInHalAidl(
             const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
             const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream,
+            const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>& vext,
             const sp<MicrophoneInfoProvider>& micInfoProvider);
 
     ~StreamInHalAidl() override = default;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
index 8210f7d..8f011c8 100644
--- a/media/libaudiohal/tests/Android.bp
+++ b/media/libaudiohal/tests/Android.bp
@@ -21,34 +21,34 @@
 }
 
 cc_defaults {
-    name: "AudioHalTestDefaults",
+    name: "libaudiohal_aidl_test_default",
     test_suites: ["device-tests"],
     defaults: [
-        "latest_android_media_audio_common_types_ndk_shared",
+        "libaudiohal_default",
+        "libaudiohal_aidl_default",
     ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-Wthread-safety",
-        "-DBACKEND_NDK",
-    ],
-
     shared_libs: [
-        "audioclient-types-aidl-cpp",
-        "libaudio_aidl_conversion_common_ndk",
         "libaudiohal",
-        "liblog",
-        "libutils",
-        "libvibrator",
     ],
 }
 
 cc_test {
+    name: "CoreAudioHalAidlTest",
+    srcs: [
+        "CoreAudioHalAidl_test.cpp",
+        ":core_audio_hal_aidl_src_files",
+    ],
+    defaults: ["libaudiohal_aidl_test_default"],
+    header_libs: ["libaudiohalimpl_headers"],
+}
+
+cc_test {
     name: "EffectsFactoryHalInterfaceTest",
     srcs: ["EffectsFactoryHalInterface_test.cpp"],
-    defaults: ["AudioHalTestDefaults"],
-    header_libs: ["libaudiohal_headers"],
+    defaults: ["libaudiohal_aidl_test_default"],
+    shared_libs: [
+        "libvibrator",
+    ],
 }
 
 cc_test {
@@ -58,15 +58,8 @@
         ":audio_effectproxy_src_files",
     ],
     defaults: [
-        "AudioHalTestDefaults",
-        "latest_android_hardware_audio_effect_ndk_shared",
-        "libaudiohal_default",
+        "libaudiohal_aidl_test_default",
         "use_libaidlvintf_gtest_helper_static",
     ],
-    shared_libs: [
-        "android.hardware.common.fmq-V1-ndk",
-        "libbinder_ndk",
-        "libfmq",
-    ],
     header_libs: ["libaudiohalimpl_headers"],
 }
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
new file mode 100644
index 0000000..ea20794
--- /dev/null
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -0,0 +1,607 @@
+/*
+ * Copyright 2023 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 <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "CoreAudioHalAidlTest"
+#include <gtest/gtest.h>
+
+#include <DeviceHalAidl.h>
+#include <StreamHalAidl.h>
+#include <aidl/android/hardware/audio/core/BnModule.h>
+#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
+#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
+#include <aidl/android/media/audio/common/Int.h>
+#include <utils/Log.h>
+
+namespace {
+
+using ::aidl::android::hardware::audio::core::VendorParameter;
+
+class VendorParameterMock {
+  public:
+    const std::vector<std::string>& getRetrievedParameterIds() const { return mGetParameterIds; }
+    const std::vector<VendorParameter>& getAsyncParameters() const { return mAsyncParameters; }
+    const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
+
+  protected:
+    ndk::ScopedAStatus getVendorParametersImpl(const std::vector<std::string>& in_parameterIds) {
+        mGetParameterIds.insert(mGetParameterIds.end(), in_parameterIds.begin(),
+                                in_parameterIds.end());
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setVendorParametersImpl(const std::vector<VendorParameter>& in_parameters,
+                                               bool async) {
+        if (async) {
+            mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(),
+                                    in_parameters.end());
+        } else {
+            mSyncParameters.insert(mSyncParameters.end(), in_parameters.begin(),
+                                   in_parameters.end());
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+
+  private:
+    std::vector<std::string> mGetParameterIds;
+    std::vector<VendorParameter> mAsyncParameters;
+    std::vector<VendorParameter> mSyncParameters;
+};
+
+class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
+                   public VendorParameterMock {
+  public:
+    bool isScreenTurnedOn() const { return mIsScreenTurnedOn; }
+    ScreenRotation getScreenRotation() const { return mScreenRotation; }
+
+  private:
+    ndk::ScopedAStatus setModuleDebug(
+            const ::aidl::android::hardware::audio::core::ModuleDebug&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getTelephony(
+            std::shared_ptr<::aidl::android::hardware::audio::core::ITelephony>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getBluetooth(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IBluetooth>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getBluetoothA2dp(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothA2dp>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getBluetoothLe(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus connectExternalDevice(
+            const ::aidl::android::media::audio::common::AudioPort&,
+            ::aidl::android::media::audio::common::AudioPort*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus disconnectExternalDevice(int32_t) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPatches(
+            std::vector<::aidl::android::hardware::audio::core::AudioPatch>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPort(int32_t,
+                                    ::aidl::android::media::audio::common::AudioPort*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPortConfigs(
+            std::vector<::aidl::android::media::audio::common::AudioPortConfig>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioPorts(
+            std::vector<::aidl::android::media::audio::common::AudioPort>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioRoutes(
+            std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioRoutesForAudioPort(
+            int32_t, std::vector<::aidl::android::hardware::audio::core::AudioRoute>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus openInputStream(const OpenInputStreamArguments&,
+                                       OpenInputStreamReturn*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
+                                        OpenOutputStreamReturn*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setAudioPatch(const ::aidl::android::hardware::audio::core::AudioPatch&,
+                                     ::aidl::android::hardware::audio::core::AudioPatch*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setAudioPortConfig(
+            const ::aidl::android::media::audio::common::AudioPortConfig&,
+            ::aidl::android::media::audio::common::AudioPortConfig*, bool*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus resetAudioPatch(int32_t) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus resetAudioPortConfig(int32_t) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMasterMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setMasterMute(bool) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMasterVolume(float*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setMasterVolume(float) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMicMute(bool*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus setMicMute(bool) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getMicrophones(
+            std::vector<::aidl::android::media::audio::common::MicrophoneInfo>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateAudioMode(::aidl::android::media::audio::common::AudioMode) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateScreenRotation(ScreenRotation in_rotation) override {
+        mScreenRotation = in_rotation;
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override {
+        mIsScreenTurnedOn = in_isTurnedOn;
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getSoundDose(
+            std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose>*)
+            override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus generateHwAvSyncId(int32_t*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+                                           std::vector<VendorParameter>*) override {
+        return getVendorParametersImpl(in_parameterIds);
+    }
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool async) override {
+        return setVendorParametersImpl(in_parameters, async);
+    }
+    ndk::ScopedAStatus addDeviceEffect(
+            int32_t,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus removeDeviceEffect(
+            int32_t,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getMmapPolicyInfos(
+            ::aidl::android::media::audio::common::AudioMMapPolicyType,
+            std::vector<::aidl::android::media::audio::common::AudioMMapPolicyInfo>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus supportsVariableLatency(bool*) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getAAudioMixerBurstCount(int32_t*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAAudioHardwareBurstMinUsec(int32_t*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+
+    bool mIsScreenTurnedOn = false;
+    ScreenRotation mScreenRotation = ScreenRotation::DEG_0;
+};
+
+class StreamCommonMock : public ::aidl::android::hardware::audio::core::BnStreamCommon,
+                         public VendorParameterMock {
+    ndk::ScopedAStatus close() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus prepareToClose() override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus updateHwAvSyncId(int32_t) override { return ndk::ScopedAStatus::ok(); }
+    ndk::ScopedAStatus getVendorParameters(const std::vector<std::string>& in_parameterIds,
+                                           std::vector<VendorParameter>*) override {
+        return getVendorParametersImpl(in_parameterIds);
+    }
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool async) override {
+        return setVendorParametersImpl(in_parameters, async);
+    }
+    ndk::ScopedAStatus addEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus removeEffect(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+VendorParameter makeVendorParameter(const std::string& id, int value) {
+    VendorParameter result{.id = id};
+    // Note: in real life, a parcelable type defined by vendor must be used,
+    // here we use Int just for test purposes.
+    ::aidl::android::media::audio::common::Int vendorValue{.value = value};
+    result.ext.setParcelable(std::move(vendorValue));
+    return result;
+}
+
+android::status_t parseVendorParameter(const VendorParameter& param, int* value) {
+    std::optional<::aidl::android::media::audio::common::Int> vendorValue;
+    RETURN_STATUS_IF_ERROR(param.ext.getParcelable(&vendorValue));
+    if (!vendorValue.has_value()) return android::BAD_VALUE;
+    *value = vendorValue.value().value;
+    return android::OK;
+}
+
+class TestHalAdapterVendorExtension
+    : public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
+  public:
+    static const std::string kLegacyParameterKey;
+    static const std::string kLegacyAsyncParameterKey;
+    static const std::string kModuleVendorParameterId;
+    static const std::string kStreamVendorParameterId;
+
+  private:
+    ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
+                                               const std::string& in_rawKeys,
+                                               std::vector<std::string>* _aidl_return) override {
+        android::AudioParameter keys(android::String8(in_rawKeys.c_str()));
+        for (size_t i = 0; i < keys.size(); ++i) {
+            android::String8 key;
+            if (android::status_t status = keys.getAt(i, key); status != android::OK) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+            switch (in_scope) {
+                case ParameterScope::MODULE:
+                    if (key == android::String8(kLegacyParameterKey.c_str()) ||
+                        key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+                        _aidl_return->push_back(kModuleVendorParameterId);
+                    } else {
+                        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                    }
+                    break;
+                case ParameterScope::STREAM:
+                    if (key == android::String8(kLegacyParameterKey.c_str()) ||
+                        key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+                        _aidl_return->push_back(kStreamVendorParameterId);
+                    } else {
+                        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                    }
+                    break;
+            }
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus parseVendorParameters(
+            ParameterScope in_scope, const std::string& in_rawKeysAndValues,
+            std::vector<VendorParameter>* out_syncParameters,
+            std::vector<VendorParameter>* out_asyncParameters) override {
+        android::AudioParameter legacy(android::String8(in_rawKeysAndValues.c_str()));
+        for (size_t i = 0; i < legacy.size(); ++i) {
+            android::String8 key;
+            if (android::status_t status = legacy.getAt(i, key); status != android::OK) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+            int value;
+            if (android::status_t status = legacy.getInt(key, value); status != android::OK) {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+            std::string parameterId;
+            switch (in_scope) {
+                case ParameterScope::MODULE:
+                    parameterId = kModuleVendorParameterId;
+                    break;
+                case ParameterScope::STREAM:
+                    parameterId = kStreamVendorParameterId;
+                    break;
+            }
+            if (key == android::String8(kLegacyParameterKey.c_str())) {
+                out_syncParameters->push_back(makeVendorParameter(parameterId, value));
+            } else if (key == android::String8(kLegacyAsyncParameterKey.c_str())) {
+                out_asyncParameters->push_back(makeVendorParameter(parameterId, value));
+            } else {
+                return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+            }
+        }
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
+            const std::string&, std::vector<VendorParameter>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string&,
+                                                          std::vector<VendorParameter>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
+                                               const std::vector<VendorParameter>& in_parameters,
+                                               std::string* _aidl_return) override {
+        android::AudioParameter legacy;
+        for (const auto& vendorParam : in_parameters) {
+            if ((in_scope == ParameterScope::MODULE &&
+                 vendorParam.id == kModuleVendorParameterId) ||
+                (in_scope == ParameterScope::STREAM &&
+                 vendorParam.id == kStreamVendorParameterId)) {
+                int value;
+                if (android::status_t status = parseVendorParameter(vendorParam, &value);
+                    status != android::OK) {
+                    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+                }
+                legacy.addInt(android::String8(kLegacyParameterKey.c_str()), value);
+            }
+        }
+        *_aidl_return = legacy.toString().c_str();
+        return ndk::ScopedAStatus::ok();
+    }
+};
+
+const std::string TestHalAdapterVendorExtension::kLegacyParameterKey = "aosp_test_param";
+const std::string TestHalAdapterVendorExtension::kLegacyAsyncParameterKey = "aosp_test_param_async";
+// Note: in real life, there is no need to explicitly separate "module" and "stream"
+// parameters, here it's done just for test purposes.
+const std::string TestHalAdapterVendorExtension::kModuleVendorParameterId =
+        "aosp.test.module.parameter";
+const std::string TestHalAdapterVendorExtension::kStreamVendorParameterId =
+        "aosp.test.stream.parameter";
+
+android::String8 createParameterString(const std::string& key, const std::string& value) {
+    android::AudioParameter params;
+    params.add(android::String8(key.c_str()), android::String8(value.c_str()));
+    return params.toString();
+}
+
+android::String8 createParameterString(const std::string& key, int value) {
+    android::AudioParameter params;
+    params.addInt(android::String8(key.c_str()), value);
+    return params.toString();
+}
+
+template <typename>
+struct mf_traits {};
+template <class T, class U>
+struct mf_traits<U T::*> {
+    using member_type = U;
+};
+
+}  // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace aidl::android::hardware::audio::core {
+template <typename P>
+std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+                 std::ostream&>
+operator<<(std::ostream& os, const P& p) {
+    return os << p.toString();
+}
+template <typename E>
+std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+    return os << toString(e);
+}
+}  // namespace aidl::android::hardware::audio::core
+
+using namespace android;
+
+class DeviceHalAidlTest : public testing::Test {
+  public:
+    void SetUp() override {
+        mModule = ndk::SharedRefBase::make<ModuleMock>();
+        mDevice = sp<DeviceHalAidl>::make("test", mModule, nullptr /*vext*/);
+    }
+    void TearDown() override {
+        mDevice.clear();
+        mModule.reset();
+    }
+
+  protected:
+    std::shared_ptr<ModuleMock> mModule;
+    sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlTest, ScreenState) {
+    EXPECT_FALSE(mModule->isScreenTurnedOn());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+                                                               AudioParameter::valueOn)));
+    EXPECT_TRUE(mModule->isScreenTurnedOn());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(AudioParameter::keyScreenState,
+                                                               AudioParameter::valueOff)));
+    EXPECT_FALSE(mModule->isScreenTurnedOn());
+    // The adaptation layer only logs a warning.
+    EXPECT_EQ(OK, mDevice->setParameters(
+                          createParameterString(AudioParameter::keyScreenState, "blah")));
+    EXPECT_FALSE(mModule->isScreenTurnedOn());
+}
+
+TEST_F(DeviceHalAidlTest, ScreenRotation) {
+    using ScreenRotation = ::aidl::android::hardware::audio::core::IModule::ScreenRotation;
+    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+    EXPECT_EQ(OK,
+              mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 90)));
+    EXPECT_EQ(ScreenRotation::DEG_90, mModule->getScreenRotation());
+    EXPECT_EQ(OK,
+              mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 0)));
+    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+    // The adaptation layer only logs a warning.
+    EXPECT_EQ(OK,
+              mDevice->setParameters(createParameterString(AudioParameter::keyScreenRotation, 42)));
+    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
+}
+
+// Without a vendor extension, any unrecognized parameters must be ignored.
+TEST_F(DeviceHalAidlTest, VendorParameterIgnored) {
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString("random_name", "random_value")));
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+
+    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+    String8 values;
+    EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
+    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+    EXPECT_TRUE(values.empty());
+}
+
+class DeviceHalAidlVendorParametersTest : public testing::Test {
+  public:
+    void SetUp() override {
+        mModule = ndk::SharedRefBase::make<ModuleMock>();
+        mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+        mDevice = sp<DeviceHalAidl>::make("test", mModule, mVendorExt);
+    }
+    void TearDown() override {
+        mDevice.clear();
+        mVendorExt.reset();
+        mModule.reset();
+    }
+
+  protected:
+    std::shared_ptr<ModuleMock> mModule;
+    std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+    sp<DeviceHalAidl> mDevice;
+};
+
+TEST_F(DeviceHalAidlVendorParametersTest, GetVendorParameter) {
+    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
+    String8 values;
+    EXPECT_EQ(OK, mDevice->getParameters(
+                          String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
+                          &values));
+    EXPECT_EQ(1UL, mModule->getRetrievedParameterIds().size());
+    if (mModule->getRetrievedParameterIds().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+                  mModule->getRetrievedParameterIds()[0]);
+    }
+}
+
+TEST_F(DeviceHalAidlVendorParametersTest, SetVendorParameter) {
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mModule->getSyncParameters().size());
+    EXPECT_EQ(OK, mDevice->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
+    EXPECT_EQ(1UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mModule->getSyncParameters().size());
+    if (mModule->getSyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+                  mModule->getSyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK, parseVendorParameter(mModule->getSyncParameters()[0], &value));
+        EXPECT_EQ(42, value);
+    }
+    if (mModule->getAsyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kModuleVendorParameterId,
+                  mModule->getAsyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK, parseVendorParameter(mModule->getAsyncParameters()[0], &value));
+        EXPECT_EQ(43, value);
+    }
+}
+
+TEST_F(DeviceHalAidlVendorParametersTest, SetInvalidVendorParameters) {
+    android::AudioParameter legacy;
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
+                  43);
+    legacy.addInt(android::String8("random_name"), 44);
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+    // TestHalAdapterVendorExtension throws an error for unknown parameters.
+    EXPECT_EQ(android::BAD_VALUE, mDevice->setParameters(legacy.toString()));
+    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
+}
+
+class StreamHalAidlVendorParametersTest : public testing::Test {
+  public:
+    void SetUp() override {
+        mStreamCommon = ndk::SharedRefBase::make<StreamCommonMock>();
+        mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
+        struct audio_config config = AUDIO_CONFIG_INITIALIZER;
+        ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
+        mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/,
+                                          StreamContextAidl(descriptor, false /*isAsynchronous*/),
+                                          mStreamCommon, mVendorExt);
+    }
+    void TearDown() override {
+        mStream.clear();
+        mVendorExt.reset();
+        mStreamCommon.reset();
+    }
+
+  protected:
+    std::shared_ptr<StreamCommonMock> mStreamCommon;
+    std::shared_ptr<TestHalAdapterVendorExtension> mVendorExt;
+    sp<StreamHalAidl> mStream;
+};
+
+TEST_F(StreamHalAidlVendorParametersTest, GetVendorParameter) {
+    EXPECT_EQ(0UL, mStreamCommon->getRetrievedParameterIds().size());
+    String8 values;
+    EXPECT_EQ(OK, mStream->getParameters(
+                          String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()),
+                          &values));
+    EXPECT_EQ(1UL, mStreamCommon->getRetrievedParameterIds().size());
+    if (mStreamCommon->getRetrievedParameterIds().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+                  mStreamCommon->getRetrievedParameterIds()[0]);
+    }
+}
+
+TEST_F(StreamHalAidlVendorParametersTest, SetVendorParameter) {
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+    EXPECT_EQ(OK, mStream->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyParameterKey, 42)));
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
+    EXPECT_EQ(OK, mStream->setParameters(createParameterString(
+                          TestHalAdapterVendorExtension::kLegacyAsyncParameterKey, 43)));
+    EXPECT_EQ(1UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(1UL, mStreamCommon->getSyncParameters().size());
+    if (mStreamCommon->getSyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+                  mStreamCommon->getSyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK, parseVendorParameter(mStreamCommon->getSyncParameters()[0], &value));
+        EXPECT_EQ(42, value);
+    }
+    if (mStreamCommon->getAsyncParameters().size() >= 1) {
+        EXPECT_EQ(TestHalAdapterVendorExtension::kStreamVendorParameterId,
+                  mStreamCommon->getAsyncParameters()[0].id);
+        int value{};
+        EXPECT_EQ(android::OK,
+                  parseVendorParameter(mStreamCommon->getAsyncParameters()[0], &value));
+        EXPECT_EQ(43, value);
+    }
+}
+
+TEST_F(StreamHalAidlVendorParametersTest, SetInvalidVendorParameters) {
+    android::AudioParameter legacy;
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyParameterKey.c_str()), 42);
+    legacy.addInt(android::String8(TestHalAdapterVendorExtension::kLegacyAsyncParameterKey.c_str()),
+                  43);
+    legacy.addInt(android::String8("random_name"), 44);
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+    // TestHalAdapterVendorExtension throws an error for unknown parameters.
+    EXPECT_EQ(android::BAD_VALUE, mStream->setParameters(legacy.toString()));
+    EXPECT_EQ(0UL, mStreamCommon->getAsyncParameters().size());
+    EXPECT_EQ(0UL, mStreamCommon->getSyncParameters().size());
+}
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index a61a1bc..3832e90 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -33,6 +33,7 @@
 const char * const AudioParameter::keyFrameCount = AUDIO_PARAMETER_STREAM_FRAME_COUNT;
 const char * const AudioParameter::keyInputSource = AUDIO_PARAMETER_STREAM_INPUT_SOURCE;
 const char * const AudioParameter::keyScreenState = AUDIO_PARAMETER_KEY_SCREEN_STATE;
+const char * const AudioParameter::keyScreenRotation = AUDIO_PARAMETER_KEY_ROTATION;
 const char * const AudioParameter::keyClosing = AUDIO_PARAMETER_KEY_CLOSING;
 const char * const AudioParameter::keyExiting = AUDIO_PARAMETER_KEY_EXITING;
 const char * const AudioParameter::keyBtSco = AUDIO_PARAMETER_KEY_BT_SCO;
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 70f8af3..8568b8f 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -41,6 +41,7 @@
     //  keyInputSource: to change audio input source, value is an int in audio_source_t
     //     (defined in media/mediarecorder.h)
     //  keyScreenState: either "on" or "off"
+    //  keyScreenRotation: one of: 0, 90, 180, 270
     static const char * const keyRouting;
     static const char * const keySamplingRate;
     static const char * const keyFormat;
@@ -48,6 +49,7 @@
     static const char * const keyFrameCount;
     static const char * const keyInputSource;
     static const char * const keyScreenState;
+    static const char * const keyScreenRotation;
 
     // TODO(b/73175392) consider improvement to AIDL StreamOut interface.
     // keyClosing: "true" when AudioOutputDescriptor is closing.  Used by A2DP HAL.
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 1d570b7..8b76842 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -7,9 +7,13 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
-cc_library_static {
+cc_library {
     name: "libaudiopolicycomponents",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     srcs: [
         "src/AudioCollections.cpp",
         "src/AudioInputDescriptor.cpp",
@@ -31,7 +35,11 @@
         "src/TypeConverter.cpp",
     ],
     shared_libs: [
+        "audioclient-types-aidl-cpp",
+        "audiopolicy-types-aidl-cpp",
+        "libaudioclient_aidl_conversion",
         "libaudiofoundation",
+        "libaudiopolicy",
         "libbase",
         "libcutils",
         "libhidlbase",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 32c78a1..1f6002f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -23,6 +23,7 @@
 
 #include <DeviceDescriptor.h>
 #include <HwModule.h>
+#include <android/media/AudioPolicyConfig.h>
 #include <error/Result.h>
 #include <utils/StrongPointer.h>
 #include <utils/RefBase.h>
@@ -42,6 +43,8 @@
     // Surround formats, with an optional list of subformats that are equivalent from users' POV.
     using SurroundFormats = std::unordered_map<audio_format_t, std::unordered_set<audio_format_t>>;
 
+    // The source used to indicate the configuration from the AIDL HAL.
+    static const constexpr char* const kAidlConfigSource = "AIDL HAL";
     // The source used to indicate the default fallback configuration.
     static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
     // The suffix of the "engine default" implementation shared library name.
@@ -49,6 +52,9 @@
 
     // Creates the default (fallback) configuration.
     static sp<const AudioPolicyConfig> createDefault();
+    // Attempts to load the configuration from the AIDL config falls back to default on failure.
+    static sp<const AudioPolicyConfig> loadFromApmAidlConfigWithFallback(
+            const media::AudioPolicyConfig& aidl);
     // Attempts to load the configuration from the XML file, falls back to default on failure.
     // If the XML file path is not provided, uses `audio_get_audio_policy_config_file` function.
     static sp<const AudioPolicyConfig> loadFromApmXmlConfigWithFallback(
@@ -140,6 +146,7 @@
     AudioPolicyConfig() = default;
 
     void augmentData();
+    status_t loadFromAidl(const media::AudioPolicyConfig& aidl);
     status_t loadFromXml(const std::string& xmlFilePath, bool forVts);
 
     std::string mSource;  // Not kDefaultConfigSource. Empty source means an empty config.
diff --git a/services/audiopolicy/common/managerdefinitions/include/HwModule.h b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
index 436fcc1..e994758 100644
--- a/services/audiopolicy/common/managerdefinitions/include/HwModule.h
+++ b/services/audiopolicy/common/managerdefinitions/include/HwModule.h
@@ -39,7 +39,8 @@
 class HwModule : public RefBase
 {
 public:
-    explicit HwModule(const char *name, uint32_t halVersionMajor = 0, uint32_t halVersionMinor = 0);
+    explicit HwModule(const char *name, uint32_t halVersionMajor, uint32_t halVersionMinor);
+    HwModule(const char *name, uint32_t halVersion = 0);
     ~HwModule();
 
     const char *getName() const { return mName.string(); }
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 42c76e2..e214ae9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -19,6 +19,9 @@
 #include <AudioPolicyConfig.h>
 #include <IOProfile.h>
 #include <Serializer.h>
+#include <hardware/audio.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
 #include <media/AudioProfile.h>
 #include <system/audio.h>
 #include <system/audio_config.h>
@@ -26,6 +29,142 @@
 
 namespace android {
 
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+
+namespace {
+
+ConversionResult<sp<PolicyAudioPort>>
+aidl2legacy_portId_PolicyAudioPort(int32_t portId,
+        const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+    if (auto it = ports.find(portId); it != ports.end()) {
+        return it->second;
+    }
+    return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<sp<AudioRoute>>
+aidl2legacy_AudioRoute(const media::AudioRoute& aidl,
+        const std::unordered_map<int32_t, sp<PolicyAudioPort>>& ports) {
+    auto legacy = sp<AudioRoute>::make(aidl.isExclusive ? AUDIO_ROUTE_MUX : AUDIO_ROUTE_MIX);
+    auto legacySink = VALUE_OR_RETURN(aidl2legacy_portId_PolicyAudioPort(aidl.sinkPortId, ports));
+    legacy->setSink(legacySink);
+    PolicyAudioPortVector legacySources;
+    for (int32_t portId : aidl.sourcePortIds) {
+        sp<PolicyAudioPort> legacyPort = VALUE_OR_RETURN(
+                aidl2legacy_portId_PolicyAudioPort(portId, ports));
+        legacySources.add(legacyPort);
+    }
+    legacy->setSources(legacySources);
+    legacySink->addRoute(legacy);
+    for (const auto& legacySource : legacySources) {
+        legacySource->addRoute(legacy);
+    }
+    return legacy;
+}
+
+status_t aidl2legacy_AudioHwModule_HwModule(const media::AudioHwModule& aidl,
+        sp<HwModule>* legacy,
+        DeviceVector* attachedInputDevices, DeviceVector* attachedOutputDevices,
+        sp<DeviceDescriptor>* defaultOutputDevice) {
+    *legacy = sp<HwModule>::make(aidl.name.c_str(), AUDIO_DEVICE_API_VERSION_CURRENT);
+    audio_module_handle_t legacyHandle = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_int32_t_audio_module_handle_t(aidl.handle));
+    (*legacy)->setHandle(legacyHandle);
+    IOProfileCollection mixPorts;
+    DeviceVector devicePorts;
+    const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+    std::unordered_map<int32_t, sp<PolicyAudioPort>> ports;
+    for (const auto& aidlPort : aidl.ports) {
+        const bool isInput = aidlPort.flags.getTag() == AudioIoFlags::input;
+        audio_port_v7 legacyPort = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioPort_audio_port_v7(aidlPort, isInput));
+        // This conversion fills out both 'hal' and 'sys' parts.
+        media::AudioPortFw fwPort = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_port_v7_AudioPortFw(legacyPort));
+        // Since audio_port_v7 lacks some fields, for example, 'maxOpen/ActiveCount',
+        // replace the converted data with the actual data from the HAL.
+        fwPort.hal = aidlPort;
+        if (aidlPort.ext.getTag() == AudioPortExt::mix) {
+            auto mixPort = sp<IOProfile>::make("", AUDIO_PORT_ROLE_NONE);
+            RETURN_STATUS_IF_ERROR(mixPort->readFromParcelable(fwPort));
+            sortAudioProfiles(mixPort->getAudioProfiles());
+            mixPorts.add(mixPort);
+            ports.emplace(aidlPort.id, mixPort);
+        } else if (aidlPort.ext.getTag() == AudioPortExt::device) {
+            // In the legacy XML, device ports use 'tagName' instead of 'AudioPort.name'.
+            auto devicePort =
+                    sp<DeviceDescriptor>::make(AUDIO_DEVICE_NONE, aidlPort.name);
+            RETURN_STATUS_IF_ERROR(devicePort->readFromParcelable(fwPort));
+            devicePort->setName("");
+            auto& profiles = devicePort->getAudioProfiles();
+            if (profiles.empty()) {
+                profiles.add(AudioProfile::createFullDynamic(gDynamicFormat));
+            } else {
+                sortAudioProfiles(profiles);
+            }
+            devicePorts.add(devicePort);
+            ports.emplace(aidlPort.id, devicePort);
+
+            if (const auto& deviceExt = aidlPort.ext.get<AudioPortExt::device>();
+                    deviceExt.device.type.connection.empty()) {  // Attached device
+                if (isInput) {
+                    attachedInputDevices->add(devicePort);
+                } else {
+                    attachedOutputDevices->add(devicePort);
+                    if ((deviceExt.flags & defaultDeviceFlag) != 0) {
+                        *defaultOutputDevice = devicePort;
+                    }
+                }
+            }
+        } else {
+            return BAD_VALUE;
+        }
+    }
+    (*legacy)->setProfiles(mixPorts);
+    (*legacy)->setDeclaredDevices(devicePorts);
+    AudioRouteVector routes;
+    for (const auto& aidlRoute : aidl.routes) {
+        sp<AudioRoute> legacy = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioRoute(aidlRoute, ports));
+        routes.add(legacy);
+    }
+    (*legacy)->setRoutes(routes);
+    return OK;
+}
+
+status_t aidl2legacy_AudioHwModules_HwModuleCollection(
+        const std::vector<media::AudioHwModule>& aidl,
+        HwModuleCollection* legacyModules, DeviceVector* attachedInputDevices,
+        DeviceVector* attachedOutputDevices, sp<DeviceDescriptor>* defaultOutputDevice) {
+    for (const auto& aidlModule : aidl) {
+        sp<HwModule> legacy;
+        RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModule_HwModule(aidlModule, &legacy,
+                        attachedInputDevices, attachedOutputDevices, defaultOutputDevice));
+        legacyModules->add(legacy);
+    }
+    return OK;
+}
+
+using SurroundFormatFamily = AudioPolicyConfig::SurroundFormats::value_type;
+ConversionResult<SurroundFormatFamily>
+aidl2legacy_SurroundFormatFamily(const media::SurroundSoundConfig::SurroundFormatFamily& aidl) {
+    audio_format_t legacyPrimary = VALUE_OR_RETURN(
+            aidl2legacy_AudioFormatDescription_audio_format_t(aidl.primaryFormat));
+    std::unordered_set<audio_format_t> legacySubs = VALUE_OR_RETURN(
+            convertContainer<std::unordered_set<audio_format_t>>(
+                    aidl.subFormats, aidl2legacy_AudioFormatDescription_audio_format_t));
+    return std::make_pair(legacyPrimary, legacySubs);
+}
+
+ConversionResult<AudioPolicyConfig::SurroundFormats>
+aidl2legacy_SurroundSoundConfig_SurroundFormats(const media::SurroundSoundConfig& aidl) {
+    return convertContainer<AudioPolicyConfig::SurroundFormats>(aidl.formatFamilies,
+            aidl2legacy_SurroundFormatFamily);
+};
+
+}  // namespace
+
 // static
 sp<const AudioPolicyConfig> AudioPolicyConfig::createDefault() {
     auto config = sp<AudioPolicyConfig>::make();
@@ -34,6 +173,16 @@
 }
 
 // static
+sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmAidlConfigWithFallback(
+        const media::AudioPolicyConfig& aidl) {
+    auto config = sp<AudioPolicyConfig>::make();
+    if (status_t status = config->loadFromAidl(aidl); status == NO_ERROR) {
+        return config;
+    }
+    return createDefault();
+}
+
+// static
 sp<const AudioPolicyConfig> AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
         const std::string& xmlFilePath) {
     const std::string filePath =
@@ -100,6 +249,18 @@
     }
 }
 
+status_t AudioPolicyConfig::loadFromAidl(const media::AudioPolicyConfig& aidl) {
+    RETURN_STATUS_IF_ERROR(aidl2legacy_AudioHwModules_HwModuleCollection(aidl.modules,
+                    &mHwModules, &mInputDevices, &mOutputDevices, &mDefaultOutputDevice));
+    mIsCallScreenModeSupported = std::find(aidl.supportedModes.begin(), aidl.supportedModes.end(),
+            media::audio::common::AudioMode::CALL_SCREEN) != aidl.supportedModes.end();
+    mSurroundFormats = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
+    mSource = kAidlConfigSource;
+    // No need to augmentData() as AIDL HAL must provide correct mic addresses.
+    return NO_ERROR;
+}
+
 status_t AudioPolicyConfig::loadFromXml(const std::string& xmlFilePath, bool forVts) {
     if (xmlFilePath.empty()) {
         ALOGE("Audio policy configuration file name is empty");
@@ -131,7 +292,8 @@
     mOutputDevices.add(mDefaultOutputDevice);
     mInputDevices.add(defaultInputDevice);
 
-    sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
+    sp<HwModule> module = new HwModule(
+            AUDIO_HARDWARE_MODULE_ID_PRIMARY, AUDIO_DEVICE_API_VERSION_2_0);
     mHwModules.add(module);
 
     sp<OutputProfile> outProfile = new OutputProfile("primary");
diff --git a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
index 418b7eb..5f14ee4 100644
--- a/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/HwModule.cpp
@@ -33,6 +33,13 @@
     setHalVersion(halVersionMajor, halVersionMinor);
 }
 
+HwModule::HwModule(const char *name, uint32_t halVersion)
+    : mName(String8(name)),
+      mHandle(AUDIO_MODULE_HANDLE_NONE),
+      mHalVersion(halVersion)
+{
+}
+
 HwModule::~HwModule()
 {
     for (size_t i = 0; i < mOutputProfiles.size(); i++) {
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index 50c5eab..6c46c54 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -51,10 +51,10 @@
         "libaudiopolicyengine_common_headers",
     ],
     static_libs: [
-        "libaudiopolicycomponents",
         "libaudiopolicyengine_config",
     ],
     shared_libs: [
         "libaudiofoundation",
+        "libaudiopolicycomponents",
     ],
 }
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index bac51f5..b9c94a4 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -16,6 +16,9 @@
 
 #pragma once
 
+#include <functional>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
 #include <EngineConfig.h>
 #include <EngineInterface.h>
 #include <ProductStrategy.h>
@@ -113,6 +116,9 @@
     status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
             AudioDeviceTypeAddrVector &devices) const override;
 
+    engineConfig::ParsingResult loadAudioPolicyEngineConfig(
+            const media::audio::common::AudioHalEngineConfig& aidlConfig);
+
     engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
 
     const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
@@ -176,6 +182,8 @@
         const DeviceVector& availableOutputDevices, product_strategy_t strategy) const;
 
 private:
+    engineConfig::ParsingResult processParsingResult(engineConfig::ParsingResult&& rawResult);
+
     /**
      * Get media devices as the given role
      *
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 7d6a308..218aff8 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -115,10 +115,53 @@
     return PRODUCT_STRATEGY_NONE;
 }
 
+engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
+        const media::audio::common::AudioHalEngineConfig& aidlConfig)
+{
+    engineConfig::ParsingResult result = engineConfig::convert(aidlConfig);
+    if (result.parsedConfig == nullptr) {
+        ALOGE("%s: There was an error parsing AIDL data", __func__);
+        result = {std::make_unique<engineConfig::Config>(gDefaultEngineConfig), 1};
+    } else {
+        // It is allowed for the HAL to return an empty list of strategies.
+        if (result.parsedConfig->productStrategies.empty()) {
+            result.parsedConfig->productStrategies = gDefaultEngineConfig.productStrategies;
+        }
+    }
+    return processParsingResult(std::move(result));
+}
+
 engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
 {
+    auto fileExists = [](const char* path) {
+        struct stat fileStat;
+        return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
+    };
+    const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
+    engineConfig::ParsingResult result =
+            fileExists(filePath.c_str()) ?
+            engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
+    if (result.parsedConfig == nullptr) {
+        ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
+        engineConfig::Config config = gDefaultEngineConfig;
+        android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
+        result = {std::make_unique<engineConfig::Config>(config),
+                  static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
+    } else {
+        // Append for internal use only volume groups (e.g. rerouting/patch)
+        result.parsedConfig->volumeGroups.insert(
+                    std::end(result.parsedConfig->volumeGroups),
+                    std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
+    }
+    ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
+    return processParsingResult(std::move(result));
+}
+
+engineConfig::ParsingResult EngineBase::processParsingResult(
+        engineConfig::ParsingResult&& rawResult)
+{
     auto loadVolumeConfig = [](auto &volumeGroups, auto &volumeConfig) {
-        // Ensure name unicity to prevent duplicate
+        // Ensure volume group name uniqueness.
         LOG_ALWAYS_FATAL_IF(std::any_of(std::begin(volumeGroups), std::end(volumeGroups),
                                      [&volumeConfig](const auto &volumeGroup) {
                 return volumeConfig.name == volumeGroup.second->getName(); }),
@@ -158,42 +201,21 @@
         });
         return iter != end(volumeGroups);
     };
-    auto fileExists = [](const char* path) {
-        struct stat fileStat;
-        return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
-    };
 
-    const std::string filePath = xmlFilePath.empty() ? engineConfig::DEFAULT_PATH : xmlFilePath;
-    auto result = fileExists(filePath.c_str()) ?
-            engineConfig::parse(filePath.c_str()) : engineConfig::ParsingResult{};
-    if (result.parsedConfig == nullptr) {
-        ALOGD("%s: No configuration found, using default matching phone experience.", __FUNCTION__);
-        engineConfig::Config config = gDefaultEngineConfig;
-        android::status_t ret = engineConfig::parseLegacyVolumes(config.volumeGroups);
-        result = {std::make_unique<engineConfig::Config>(config),
-                  static_cast<size_t>(ret == NO_ERROR ? 0 : 1)};
-    } else {
-        // Append for internal use only volume groups (e.g. rerouting/patch)
-        result.parsedConfig->volumeGroups.insert(
-                    std::end(result.parsedConfig->volumeGroups),
-                    std::begin(gSystemVolumeGroups), std::end(gSystemVolumeGroups));
-    }
+    auto result = std::move(rawResult);
     // Append for internal use only strategies (e.g. rerouting/patch)
     result.parsedConfig->productStrategies.insert(
                 std::end(result.parsedConfig->productStrategies),
                 std::begin(gOrderedSystemStrategies), std::end(gOrderedSystemStrategies));
 
-
-    ALOGE_IF(result.nbSkippedElement != 0, "skipped %zu elements", result.nbSkippedElement);
-
     engineConfig::VolumeGroup defaultVolumeConfig;
     engineConfig::VolumeGroup defaultSystemVolumeConfig;
     for (auto &volumeConfig : result.parsedConfig->volumeGroups) {
         // save default volume config for streams not defined in configuration
-        if (volumeConfig.name.compare("AUDIO_STREAM_MUSIC") == 0) {
+        if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_MUSIC)) == 0) {
             defaultVolumeConfig = volumeConfig;
         }
-        if (volumeConfig.name.compare("AUDIO_STREAM_PATCH") == 0) {
+        if (volumeConfig.name.compare(audio_stream_type_to_string(AUDIO_STREAM_PATCH)) == 0) {
             defaultSystemVolumeConfig = volumeConfig;
         }
         loadVolumeConfig(mVolumeGroups, volumeConfig);
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index 459cc78..12597de 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -22,11 +22,13 @@
         "-Wextra",
     ],
     shared_libs: [
-        "libmedia_helper",
-        "libxml2",
-        "libutils",
-        "liblog",
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudiopolicycomponents",
         "libcutils",
+        "liblog",
+        "libmedia_helper",
+        "libutils",
+        "libxml2",
     ],
     header_libs: [
         "libaudio_system_headers",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 4de16c5..119dbd6 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -16,10 +16,11 @@
 
 #pragma once
 
-#include <system/audio.h>
-
 #include <string>
 #include <vector>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio.h>
 #include <utils/Errors.h>
 
 struct _xmlNode;
@@ -116,6 +117,7 @@
  */
 ParsingResult parse(const char* path = DEFAULT_PATH);
 android::status_t parseLegacyVolumes(VolumeGroups &volumeGroups);
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
 // Exposed for testing.
 android::status_t parseLegacyVolumeFile(const char* path, VolumeGroups &volumeGroups);
 
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index ac117f0..ca78ce7 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -14,26 +14,30 @@
  * limitations under the License.
  */
 
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
 #define LOG_TAG "APM::AudioPolicyEngine/Config"
 //#define LOG_NDEBUG 0
 
 #include "EngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
 #include <cutils/properties.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionUtil.h>
 #include <media/TypeConverter.h>
 #include <media/convert.h>
 #include <system/audio_config.h>
 #include <utils/Log.h>
-#include <libxml/parser.h>
-#include <libxml/xinclude.h>
-#include <string>
-#include <vector>
-#include <map>
-#include <sstream>
-#include <istream>
-
-#include <cstdint>
-#include <stdarg.h>
-#include <string>
 
 namespace android {
 
@@ -45,6 +49,85 @@
 static const char *const gReferenceElementName = "reference";
 static const char *const gReferenceAttributeName = "name";
 
+namespace {
+
+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));
+    legacy.volumeGroup = aidl.volumeGroupName;
+    legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
+                    aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
+    return legacy;
+}
+
+ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
+        const media::audio::common::AudioHalProductStrategy& aidl) {
+    ProductStrategy legacy;
+    legacy.name = "strategy_" + std::to_string(aidl.id);
+    legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
+                    aidl.attributesGroups,
+                    aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
+    return legacy;
+}
+
+ConversionResult<std::string> legacy_device_category_to_string(device_category legacy) {
+    std::string s;
+    if (DeviceCategoryConverter::toString(legacy, s)) {
+        return s;
+    }
+    return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<std::string> aidl2legacy_DeviceCategory(
+        const media::audio::common::AudioHalVolumeCurve::DeviceCategory aidl) {
+    using DeviceCategory = media::audio::common::AudioHalVolumeCurve::DeviceCategory;
+    switch (aidl) {
+        case DeviceCategory::HEADSET:
+            return legacy_device_category_to_string(DEVICE_CATEGORY_HEADSET);
+        case DeviceCategory::SPEAKER:
+            return legacy_device_category_to_string(DEVICE_CATEGORY_SPEAKER);
+        case DeviceCategory::EARPIECE:
+            return legacy_device_category_to_string(DEVICE_CATEGORY_EARPIECE);
+        case DeviceCategory::EXT_MEDIA:
+            return legacy_device_category_to_string(DEVICE_CATEGORY_EXT_MEDIA);
+        case DeviceCategory::HEARING_AID:
+            return legacy_device_category_to_string(DEVICE_CATEGORY_HEARING_AID);
+    }
+    return base::unexpected(BAD_VALUE);
+}
+
+ConversionResult<CurvePoint> aidl2legacy_AudioHalCurvePoint_CurvePoint(
+        const media::audio::common::AudioHalVolumeCurve::CurvePoint& aidl) {
+    CurvePoint legacy;
+    legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+    legacy.attenuationInMb = aidl.attenuationMb;
+    return legacy;
+}
+
+ConversionResult<VolumeCurve> aidl2legacy_AudioHalVolumeCurve_VolumeCurve(
+        const media::audio::common::AudioHalVolumeCurve& aidl) {
+    VolumeCurve legacy;
+    legacy.deviceCategory = VALUE_OR_RETURN(aidl2legacy_DeviceCategory(aidl.deviceCategory));
+    legacy.curvePoints = VALUE_OR_RETURN(convertContainer<CurvePoints>(
+                    aidl.curvePoints, aidl2legacy_AudioHalCurvePoint_CurvePoint));
+    return legacy;
+}
+
+ConversionResult<VolumeGroup> aidl2legacy_AudioHalVolumeGroup_VolumeGroup(
+        const media::audio::common::AudioHalVolumeGroup& aidl) {
+    VolumeGroup legacy;
+    legacy.name = aidl.name;
+    legacy.indexMin = aidl.minIndex;
+    legacy.indexMax = aidl.maxIndex;
+    legacy.volumeCurves = VALUE_OR_RETURN(convertContainer<VolumeCurves>(
+                    aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
+    return legacy;
+}
+
+}  // namespace
+
 template<typename E, typename C>
 struct BaseSerializerTraits {
     typedef E Element;
@@ -724,5 +807,25 @@
     }
 }
 
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+    auto config = std::make_unique<engineConfig::Config>();
+    config->version = 1.0f;
+    if (auto conv = convertContainer<engineConfig::ProductStrategies>(
+                    aidlConfig.productStrategies,
+                    aidl2legacy_AudioHalProductStrategy_ProductStrategy); conv.ok()) {
+        config->productStrategies = std::move(conv.value());
+    } else {
+        return ParsingResult{};
+    }
+    if (auto conv = convertContainer<engineConfig::VolumeGroups>(
+                    aidlConfig.volumeGroups,
+                    aidl2legacy_AudioHalVolumeGroup_VolumeGroup); conv.ok()) {
+        config->volumeGroups = std::move(conv.value());
+    } else {
+        return ParsingResult{};
+    }
+    return {.parsedConfig=std::move(config), .nbSkippedElement=0};
+ }
+
 } // namespace engineConfig
 } // namespace android
diff --git a/services/audiopolicy/engine/config/tests/Android.bp b/services/audiopolicy/engine/config/tests/Android.bp
index 5791f17..5d1aa16 100644
--- a/services/audiopolicy/engine/config/tests/Android.bp
+++ b/services/audiopolicy/engine/config/tests/Android.bp
@@ -11,6 +11,7 @@
     name: "audiopolicy_engineconfig_tests",
 
     shared_libs: [
+        "libaudiopolicycomponents",
         "libbase",
         "liblog",
         "libmedia_helper",
diff --git a/services/audiopolicy/engine/interface/EngineInterface.h b/services/audiopolicy/engine/interface/EngineInterface.h
index dd7ac1a..70461ad 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -20,6 +20,7 @@
 #include <utility>
 
 #include <AudioPolicyManagerObserver.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
 #include <media/AudioProductStrategy.h>
 #include <media/AudioVolumeGroup.h>
 #include <IVolumeCurves.h>
@@ -47,6 +48,14 @@
 {
 public:
     /**
+     * Loads the engine configuration from AIDL configuration data.
+     * If loading failed, tries to fall back to some default configuration. If fallback
+     * is impossible, returns an error.
+     */
+    virtual status_t loadFromHalConfigWithFallback(
+            const media::audio::common::AudioHalEngineConfig& config) = 0;
+
+    /**
      * Loads the engine configuration from the specified or the default config file.
      * If loading failed, tries to fall back to some default configuration. If fallback
      * is impossible, returns an error.
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index dc8d9cf..eb2e2f4 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -35,14 +35,15 @@
         "libaudiopolicyengineconfigurable_interface_headers",
     ],
     static_libs: [
-        "libaudiopolicycomponents",
         "libaudiopolicyengine_common",
         "libaudiopolicyengine_config",
         "libaudiopolicyengineconfigurable_pfwwrapper",
 
     ],
   shared_libs: [
+        "libaudio_aidl_conversion_common_cpp",
         "libaudiofoundation",
+        "libaudiopolicycomponents",
         "libbase",
         "liblog",
         "libcutils",
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
index 0398fc7..f7159c5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.bp
@@ -31,11 +31,11 @@
         "libaudiopolicyengineconfigurable_interface_headers",
     ],
     static_libs: [
-        "libaudiopolicycomponents",
         "libaudiopolicyengine_common",
         "libpfw_utility",
     ],
     shared_libs: [
+        "libaudiopolicycomponents",
         "libaudiopolicyengineconfigurable",
         "liblog",
         "libutils",
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 2eb0177..ccd4316 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -70,6 +70,12 @@
 {
 }
 
+status_t Engine::loadFromHalConfigWithFallback(
+        const media::audio::common::AudioHalEngineConfig& config __unused) {
+    // b/242678729. Need to implement for the configurable engine.
+    return INVALID_OPERATION;
+}
+
 status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
 {
     status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index b964cd6..4f3e620 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -41,12 +41,15 @@
     ///
     /// from EngineInterface
     ///
-    android::status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
+    status_t loadFromHalConfigWithFallback(
+            const media::audio::common::AudioHalEngineConfig& config) override;
+
+    status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
 
     ///
     /// from EngineBase
     ///
-    android::status_t initCheck() override;
+    status_t initCheck() override;
 
     status_t setPhoneState(audio_mode_t mode) override;
 
@@ -56,8 +59,8 @@
 
     audio_policy_forced_cfg_t getForceUse(audio_policy_force_use_t usage) const override;
 
-    android::status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
-                                               audio_policy_dev_state_t state) override;
+    status_t setDeviceConnectionState(const sp<DeviceDescriptor> devDesc,
+                                      audio_policy_dev_state_t state) override;
 
     DeviceVector getOutputDevicesForAttributes(const audio_attributes_t &attr,
                                                const sp<DeviceDescriptor> &preferedDevice = nullptr,
diff --git a/services/audiopolicy/enginedefault/Android.bp b/services/audiopolicy/enginedefault/Android.bp
index 4671fe9..7d4ccab 100644
--- a/services/audiopolicy/enginedefault/Android.bp
+++ b/services/audiopolicy/enginedefault/Android.bp
@@ -25,12 +25,13 @@
         "libaudiopolicyengine_interface_headers",
     ],
     static_libs: [
-        "libaudiopolicycomponents",
         "libaudiopolicyengine_common",
         "libaudiopolicyengine_config",
     ],
     shared_libs: [
+        "libaudio_aidl_conversion_common_cpp",
         "libaudiofoundation",
+        "libaudiopolicycomponents",
         "libbase",
         "liblog",
         "libcutils",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 88cbb7d..15f7842 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -35,10 +35,7 @@
 #include <utils/String8.h>
 #include <utils/Log.h>
 
-namespace android
-{
-namespace audio_policy
-{
+namespace android::audio_policy {
 
 struct legacy_strategy_map { const char *name; legacy_strategy id; };
 static const std::vector<legacy_strategy_map>& getLegacyStrategy() {
@@ -59,8 +56,18 @@
     return legacyStrategy;
 }
 
+status_t Engine::loadFromHalConfigWithFallback(
+        const media::audio::common::AudioHalEngineConfig& aidlConfig) {
+    return loadWithFallback(aidlConfig);
+}
+
 status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath) {
-    auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
+    return loadWithFallback(xmlFilePath);
+}
+
+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);
@@ -73,6 +80,7 @@
     return OK;
 }
 
+
 status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
 {
     switch(usage) {
@@ -844,5 +852,4 @@
                                            AUDIO_FORMAT_DEFAULT);
 }
 
-} // namespace audio_policy
-} // namespace android
+} // namespace android::audio_policy
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index 8410560..878bca9 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -47,10 +47,14 @@
 public:
     Engine() = default;
     virtual ~Engine() = default;
+    Engine(const Engine &object) = delete;
+    Engine &operator=(const Engine &object) = delete;
 
     ///
     /// from EngineInterface
     ///
+    status_t loadFromHalConfigWithFallback(
+            const media::audio::common::AudioHalEngineConfig& config) override;
     status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") override;
 
 private:
@@ -79,9 +83,8 @@
     DeviceVector getDevicesForProductStrategy(product_strategy_t strategy) const override;
 
 private:
-    /* Copy facilities are put private to disable copy. */
-    Engine(const Engine &object);
-    Engine &operator=(const Engine &object);
+    template<typename T>
+    status_t loadWithFallback(const T& configSource);
 
     status_t setDefaultDevice(audio_devices_t device);
 
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 621f643..c4b3751 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -38,6 +38,7 @@
         "capture_state_listener-aidl-cpp",
         "libaudioclient",
         "libaudiofoundation",
+        "libaudiopolicycomponents",
         "libbase",
         "libcutils",
         "libhidlbase",
@@ -54,7 +55,6 @@
     ],
     static_libs: [
         "android.hardware.audio.common@7.0-enums",
-        "libaudiopolicycomponents",
     ],
     header_libs: [
         "libaudiopolicycommon",
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 6e34eb0..a1785da 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -23,6 +23,7 @@
 
     shared_libs: [
         "libaudiofoundation",
+        "libaudiopolicycomponents",
         "libcutils",
         "libdl",
         "libutils",
@@ -49,8 +50,6 @@
         "libaudiopolicymanager_interface_headers",
     ],
 
-    static_libs: ["libaudiopolicycomponents"],
-
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f093e68..7d667d5 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1293,7 +1293,8 @@
         if (outputDevices.size() == 1) {
             info = getPreferredMixerAttributesInfo(
                     outputDevices.itemAt(0)->getId(),
-                    mEngine->getProductStrategyForAttributes(*resultAttr));
+                    mEngine->getProductStrategyForAttributes(*resultAttr),
+                    true /*activeBitPerfectPreferred*/);
             // Only use preferred mixer if the uid matches or the preferred mixer is bit-perfect
             // and it is currently active.
             if (info != nullptr && info->getUid() != uid &&
@@ -4485,16 +4486,24 @@
 }
 
 sp<PreferredMixerAttributesInfo> AudioPolicyManager::getPreferredMixerAttributesInfo(
-        audio_port_handle_t devicePortId, product_strategy_t strategy) {
+        audio_port_handle_t devicePortId,
+        product_strategy_t strategy,
+        bool activeBitPerfectPreferred) {
     auto it = mPreferredMixerAttrInfos.find(devicePortId);
     if (it == mPreferredMixerAttrInfos.end()) {
         return nullptr;
     }
-    auto mixerAttrInfoIt = it->second.find(strategy);
-    if (mixerAttrInfoIt == it->second.end()) {
-        return nullptr;
+    if (activeBitPerfectPreferred) {
+        for (auto [strategy, info] : it->second) {
+            if ((info->getFlags() & AUDIO_OUTPUT_FLAG_BIT_PERFECT) != AUDIO_OUTPUT_FLAG_NONE
+                && info->getActiveClientCount() != 0) {
+                return info;
+            }
+        }
     }
-    return mixerAttrInfoIt->second;
+    auto strategyMatchedMixerAttrInfoIt = it->second.find(strategy);
+    return strategyMatchedMixerAttrInfoIt == it->second.end()
+            ? nullptr : strategyMatchedMixerAttrInfoIt->second;
 }
 
 status_t AudioPolicyManager::getPreferredMixerAttributes(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 88bafef..98988e7 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1298,8 +1298,15 @@
                                        uint32_t flags,
                                        bool isInput);
 
+        /**
+         * Returns the preferred mixer attributes info for the given device port id and strategy.
+         * Bit-perfect mixer attributes will be returned if it is active and
+         * `activeBitPerfectPreferred` is true.
+         */
         sp<PreferredMixerAttributesInfo> getPreferredMixerAttributesInfo(
-                audio_port_handle_t devicePortId, product_strategy_t strategy);
+                audio_port_handle_t devicePortId,
+                product_strategy_t strategy,
+                bool activeBitPerfectPreferred = false);
 
         sp<SwAudioOutputDescriptor> reopenOutput(
                 sp<SwAudioOutputDescriptor> outputDesc,
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index 939fbc5..ab77941 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -40,6 +40,23 @@
     return engine;
 }
 
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+        const media::audio::common::AudioHalEngineConfig& config)
+{
+    auto engLib = EngineLibrary::load(librarySuffix);
+    if (!engLib) {
+        ALOGE("%s: Failed to load the engine library, suffix \"%s\"",
+                __func__, librarySuffix.c_str());
+        return nullptr;
+    }
+    auto engine = engLib->createEngineUsingHalConfig(config);
+    if (engine == nullptr) {
+        ALOGE("%s: Failed to instantiate the APM engine", __func__);
+        return nullptr;
+    }
+    return engine;
+}
+
 // static
 std::shared_ptr<EngineLibrary> EngineLibrary::load(const std::string& librarySuffix)
 {
@@ -53,7 +70,8 @@
     close();
 }
 
-EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath) {
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath)
+{
     auto instance = createEngine();
     if (instance != nullptr) {
         if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
@@ -67,6 +85,21 @@
     return nullptr;
 }
 
+EngineInstance EngineLibrary::createEngineUsingHalConfig(
+        const media::audio::common::AudioHalEngineConfig& config)
+{
+    auto instance = createEngine();
+    if (instance != nullptr) {
+        if (status_t status = instance->loadFromHalConfigWithFallback(config); status == OK) {
+            return instance;
+        } else {
+            ALOGE("%s: loading of the engine config with HAL configuration \"%s\" failed: %d",
+                    __func__, config.toString().c_str(), status);
+        }
+    }
+    return nullptr;
+}
+
 bool EngineLibrary::init(std::string libraryPath)
 {
     mLibraryHandle = dlopen(libraryPath.c_str(), 0);
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.h b/services/audiopolicy/managerdefault/EngineLibrary.h
index dc138a1..4710e34 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -21,6 +21,7 @@
 #include <string>
 
 #include <EngineInterface.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
 
 namespace android {
 
@@ -28,6 +29,8 @@
 
 EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
         const std::string& configXmlFilePath = "");
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+        const media::audio::common::AudioHalEngineConfig& config);
 
 class EngineLibrary : public std::enable_shared_from_this<EngineLibrary> {
 public:
@@ -40,6 +43,8 @@
     EngineLibrary& operator=(EngineLibrary&&) = delete;
 
     EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
+    EngineInstance createEngineUsingHalConfig(
+            const media::audio::common::AudioHalEngineConfig& config);
 
 private:
     EngineLibrary() = default;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 2f677da..f4fc8f1 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -35,6 +35,7 @@
         "libaudiofoundation",
         "libaudiohal",
         "libaudiopolicy",
+        "libaudiopolicycomponents",
         "libaudiopolicymanagerdefault",
         "libaudiousecasevalidation",
         "libaudioutils",
@@ -66,7 +67,6 @@
     ],
 
     static_libs: [
-        "libaudiopolicycomponents",
         "framework-permission-aidl-cpp",
     ],
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 2e7b3ff..5d86e7c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -318,7 +318,7 @@
     return Status::ok();
 }
 
-Status AudioPolicyService::getOutputForAttr(const media::AudioAttributesInternal& attrAidl,
+Status AudioPolicyService::getOutputForAttr(const media::audio::common::AudioAttributes& attrAidl,
                                             int32_t sessionAidl,
                                             const AttributionSourceState& attributionSource,
                                             const AudioConfig& configAidl,
@@ -327,7 +327,7 @@
                                             media::GetOutputForAttrResponse* _aidl_return)
 {
     audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_session_t session = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_session_t(sessionAidl));
     audio_stream_type_t stream = AUDIO_STREAM_DEFAULT;
@@ -440,7 +440,7 @@
         _aidl_return->isSpatialized = isSpatialized;
         _aidl_return->isBitPerfect = isBitPerfect;
         _aidl_return->attr = VALUE_OR_RETURN_BINDER_STATUS(
-                legacy2aidl_audio_attributes_t_AudioAttributesInternal(attr));
+                legacy2aidl_audio_attributes_t_AudioAttributes(attr));
     } else {
         _aidl_return->configBase.format = VALUE_OR_RETURN_BINDER_STATUS(
                 legacy2aidl_audio_format_t_AudioFormatDescription(config.format));
@@ -575,7 +575,7 @@
     mAudioPolicyManager->releaseOutput(portId);
 }
 
-Status AudioPolicyService::getInputForAttr(const media::AudioAttributesInternal& attrAidl,
+Status AudioPolicyService::getInputForAttr(const media::audio::common::AudioAttributes& attrAidl,
                                            int32_t inputAidl,
                                            int32_t riidAidl,
                                            int32_t sessionAidl,
@@ -585,7 +585,7 @@
                                            int32_t selectedDeviceIdAidl,
                                            media::GetInputForAttrResponse* _aidl_return) {
     audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_io_handle_t input = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_io_handle_t(inputAidl));
     audio_unique_id_t riid = VALUE_OR_RETURN_BINDER_STATUS(
@@ -1073,10 +1073,10 @@
 }
 
 Status AudioPolicyService::setVolumeIndexForAttributes(
-        const media::AudioAttributesInternal& attrAidl,
+        const media::audio::common::AudioAttributes& attrAidl,
         const AudioDeviceDescription& deviceAidl, int32_t indexAidl) {
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     int index = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int>(indexAidl));
     audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
@@ -1096,10 +1096,10 @@
 }
 
 Status AudioPolicyService::getVolumeIndexForAttributes(
-        const media::AudioAttributesInternal& attrAidl,
+        const media::audio::common::AudioAttributes& attrAidl,
         const AudioDeviceDescription& deviceAidl, int32_t* _aidl_return) {
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_devices_t device = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioDeviceDescription_audio_devices_t(deviceAidl));
     int index;
@@ -1118,9 +1118,9 @@
 }
 
 Status AudioPolicyService::getMinVolumeIndexForAttributes(
-        const media::AudioAttributesInternal& attrAidl, int32_t* _aidl_return) {
+        const media::audio::common::AudioAttributes& attrAidl, int32_t* _aidl_return) {
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     int index;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1137,9 +1137,9 @@
 }
 
 Status AudioPolicyService::getMaxVolumeIndexForAttributes(
-        const media::AudioAttributesInternal& attrAidl, int32_t* _aidl_return) {
+        const media::audio::common::AudioAttributes& attrAidl, int32_t* _aidl_return) {
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     int index;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             AudioValidator::validateAudioAttributes(attributes, "169572641")));
@@ -1177,12 +1177,13 @@
     return Status::ok();
 }
 
-Status AudioPolicyService::getDevicesForAttributes(const media::AudioAttributesInternal& attrAidl,
-                                                   bool forVolume,
-                                                   std::vector<AudioDevice>* _aidl_return)
+Status AudioPolicyService::getDevicesForAttributes(
+        const media::audio::common::AudioAttributes& attrAidl,
+        bool forVolume,
+        std::vector<AudioDevice>* _aidl_return)
 {
     audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     AudioDeviceTypeAddrVector devices;
 
     if (mAudioPolicyManager == NULL) {
@@ -1507,12 +1508,12 @@
 
 Status AudioPolicyService::isDirectOutputSupported(
         const AudioConfigBase& configAidl,
-        const media::AudioAttributesInternal& attributesAidl,
+        const media::audio::common::AudioAttributes& attributesAidl,
         bool* _aidl_return) {
     audio_config_base_t config = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioConfigBase_audio_config_base_t(configAidl, false /*isInput*/));
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attributesAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attributesAidl));
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             AudioValidator::validateAudioAttributes(attributes, "169572641")));
 
@@ -1829,12 +1830,12 @@
 }
 
 Status AudioPolicyService::startAudioSource(const media::AudioPortConfigFw& sourceAidl,
-                                            const media::AudioAttributesInternal& attributesAidl,
-                                            int32_t* _aidl_return) {
+        const media::audio::common::AudioAttributes& attributesAidl,
+        int32_t* _aidl_return) {
     audio_port_config source = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPortConfigFw_audio_port_config(sourceAidl));
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attributesAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attributesAidl));
     audio_port_handle_t portId;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             AudioValidator::validateAudioPortConfig(source)));
@@ -2107,10 +2108,10 @@
 }
 
 Status AudioPolicyService::getProductStrategyFromAudioAttributes(
-        const media::AudioAttributesInternal& aaAidl,
+        const media::audio::common::AudioAttributes& aaAidl,
         bool fallbackOnDefault, int32_t* _aidl_return) {
     audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(aaAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl));
     product_strategy_t productStrategy;
 
     if (mAudioPolicyManager == NULL) {
@@ -2141,10 +2142,10 @@
 }
 
 Status AudioPolicyService::getVolumeGroupFromAudioAttributes(
-        const media::AudioAttributesInternal& aaAidl,
+        const media::audio::common::AudioAttributes& aaAidl,
         bool fallbackOnDefault, int32_t* _aidl_return) {
     audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(aaAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl));
     volume_group_t volumeGroup;
 
     if (mAudioPolicyManager == NULL) {
@@ -2381,7 +2382,7 @@
 }
 
 Status AudioPolicyService::canBeSpatialized(
-        const std::optional<media::AudioAttributesInternal>& attrAidl,
+        const std::optional<media::audio::common::AudioAttributes>& attrAidl,
         const std::optional<AudioConfig>& configAidl,
         const std::vector<AudioDevice>& devicesAidl,
         bool* _aidl_return) {
@@ -2391,7 +2392,7 @@
     audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
     if (attrAidl.has_value()) {
         attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl.value()));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl.value()));
     }
     audio_config_t config = AUDIO_CONFIG_INITIALIZER;
     if (configAidl.has_value()) {
@@ -2408,9 +2409,10 @@
     return Status::ok();
 }
 
-Status AudioPolicyService::getDirectPlaybackSupport(const media::AudioAttributesInternal &attrAidl,
-                                                    const AudioConfig &configAidl,
-                                                    media::AudioDirectMode *_aidl_return) {
+Status AudioPolicyService::getDirectPlaybackSupport(
+        const media::audio::common::AudioAttributes &attrAidl,
+        const AudioConfig &configAidl,
+        media::AudioDirectMode *_aidl_return) {
     if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
@@ -2418,7 +2420,7 @@
         return binderStatusFromStatusT(BAD_VALUE);
     }
     audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_config_t config = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioConfig_audio_config_t(configAidl, false /*isInput*/));
     Mutex::Autolock _l(mLock);
@@ -2429,13 +2431,13 @@
 }
 
 Status AudioPolicyService::getDirectProfilesForAttributes(
-                                const media::AudioAttributesInternal& attrAidl,
+                                const media::audio::common::AudioAttributes& attrAidl,
                                 std::vector<media::audio::common::AudioProfile>* _aidl_return) {
    if (mAudioPolicyManager == nullptr) {
         return binderStatusFromStatusT(NO_INIT);
     }
     audio_attributes_t attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     AudioProfileVector audioProfiles;
 
     Mutex::Autolock _l(mLock);
@@ -2470,7 +2472,7 @@
 }
 
 Status AudioPolicyService::setPreferredMixerAttributes(
-        const media::AudioAttributesInternal& attrAidl,
+        const media::audio::common::AudioAttributes& attrAidl,
         int32_t portIdAidl,
         int32_t uidAidl,
         const media::AudioMixerAttributesInternal& mixerAttrAidl) {
@@ -2479,7 +2481,7 @@
     }
 
     audio_attributes_t  attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_mixer_attributes_t mixerAttr = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioMixerAttributesInternal_audio_mixer_attributes_t(mixerAttrAidl));
     uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
@@ -2492,7 +2494,7 @@
 }
 
 Status AudioPolicyService::getPreferredMixerAttributes(
-        const media::AudioAttributesInternal& attrAidl,
+        const media::audio::common::AudioAttributes& attrAidl,
         int32_t portIdAidl,
         std::optional<media::AudioMixerAttributesInternal>* _aidl_return) {
     if (mAudioPolicyManager == nullptr) {
@@ -2500,7 +2502,7 @@
     }
 
     audio_attributes_t  attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
 
@@ -2515,7 +2517,7 @@
 }
 
 Status AudioPolicyService::clearPreferredMixerAttributes(
-        const media::AudioAttributesInternal& attrAidl,
+        const media::audio::common::AudioAttributes& attrAidl,
         int32_t portIdAidl,
         int32_t uidAidl) {
     if (mAudioPolicyManager == nullptr) {
@@ -2523,7 +2525,7 @@
     }
 
     audio_attributes_t  attr = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesInternal_audio_attributes_t(attrAidl));
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     uid_t uid = VALUE_OR_RETURN_BINDER_STATUS(aidl2legacy_int32_t_uid_t(uidAidl));
     audio_port_handle_t portId = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(portIdAidl));
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 9367949..234104d 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -186,10 +186,23 @@
 
 static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
 {
-    auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();  // This can't fail.
-    AudioPolicyManager *apm = new AudioPolicyManager(
-            config, loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
-            clientInterface);
+    AudioPolicyManager *apm = nullptr;
+    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");
+        apm = new AudioPolicyManager(config,
+                loadApmEngineLibraryAndCreateEngine(
+                        config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
+                clientInterface);
+    } else {
+        auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback();  // This can't fail.
+        apm = new AudioPolicyManager(config,
+                loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+                clientInterface);
+    }
     status_t status = apm->initialize();
     if (status != NO_ERROR) {
         delete apm;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 4710a8a..d0cde64 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -98,7 +98,8 @@
     binder::Status getForceUse(media::AudioPolicyForceUse usage,
                                media::AudioPolicyForcedConfig* _aidl_return) override;
     binder::Status getOutput(AudioStreamType stream, int32_t* _aidl_return) override;
-    binder::Status getOutputForAttr(const media::AudioAttributesInternal& attr, int32_t session,
+    binder::Status getOutputForAttr(const media::audio::common::AudioAttributes& attr,
+                                    int32_t session,
                                     const AttributionSourceState &attributionSource,
                                     const AudioConfig& config,
                                     int32_t flags, int32_t selectedDeviceId,
@@ -106,7 +107,7 @@
     binder::Status startOutput(int32_t portId) override;
     binder::Status stopOutput(int32_t portId) override;
     binder::Status releaseOutput(int32_t portId) override;
-    binder::Status getInputForAttr(const media::AudioAttributesInternal& attr, int32_t input,
+    binder::Status getInputForAttr(const media::audio::common::AudioAttributes& attr, int32_t input,
                                    int32_t riid, int32_t session,
                                    const AttributionSourceState &attributionSource,
                                    const AudioConfigBase& config, int32_t flags,
@@ -123,19 +124,19 @@
     binder::Status getStreamVolumeIndex(AudioStreamType stream,
                                         const AudioDeviceDescription& device,
                                         int32_t* _aidl_return) override;
-    binder::Status setVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status setVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
                                                const AudioDeviceDescription& device,
                                                int32_t index) override;
-    binder::Status getVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status getVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
                                                const AudioDeviceDescription& device,
                                                int32_t* _aidl_return) override;
-    binder::Status getMaxVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status getMaxVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
                                                   int32_t* _aidl_return) override;
-    binder::Status getMinVolumeIndexForAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status getMinVolumeIndexForAttributes(const media::audio::common::AudioAttributes& attr,
                                                   int32_t* _aidl_return) override;
     binder::Status getStrategyForStream(AudioStreamType stream,
                                         int32_t* _aidl_return) override;
-    binder::Status getDevicesForAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status getDevicesForAttributes(const media::audio::common::AudioAttributes& attr,
                                            bool forVolume,
                                            std::vector<AudioDevice>* _aidl_return) override;
     binder::Status getOutputForEffect(const media::EffectDescriptor& desc,
@@ -170,7 +171,7 @@
     binder::Status getOffloadSupport(const media::audio::common::AudioOffloadInfo& info,
                                      media::AudioOffloadMode* _aidl_return) override;
     binder::Status isDirectOutputSupported(const AudioConfigBase& config,
-                                           const media::AudioAttributesInternal& attributes,
+                                           const media::audio::common::AudioAttributes& attributes,
                                            bool* _aidl_return) override;
     binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
                                   Int* count, std::vector<media::AudioPortFw>* ports,
@@ -201,7 +202,7 @@
             const std::vector<AudioDevice>& devices) override;
     binder::Status removeUserIdDeviceAffinities(int32_t userId) override;
     binder::Status startAudioSource(const media::AudioPortConfigFw& source,
-                                    const media::AudioAttributesInternal& attributes,
+                                    const media::audio::common::AudioAttributes& attributes,
                                     int32_t* _aidl_return) override;
     binder::Status stopAudioSource(int32_t portId) override;
     binder::Status setMasterMono(bool mono) override;
@@ -228,14 +229,16 @@
     binder::Status isHotwordStreamSupported(bool lookbackAudio, bool* _aidl_return) override;
     binder::Status listAudioProductStrategies(
             std::vector<media::AudioProductStrategy>* _aidl_return) override;
-    binder::Status getProductStrategyFromAudioAttributes(const media::AudioAttributesInternal& aa,
-                                                         bool fallbackOnDefault,
-                                                         int32_t* _aidl_return) override;
+    binder::Status getProductStrategyFromAudioAttributes(
+            const media::audio::common::AudioAttributes& aa,
+            bool fallbackOnDefault,
+            int32_t* _aidl_return) override;
     binder::Status listAudioVolumeGroups(
             std::vector<media::AudioVolumeGroup>* _aidl_return) override;
-    binder::Status getVolumeGroupFromAudioAttributes(const media::AudioAttributesInternal& aa,
-                                                     bool fallbackOnDefault,
-                                                     int32_t* _aidl_return) override;
+    binder::Status getVolumeGroupFromAudioAttributes(
+            const media::audio::common::AudioAttributes& aa,
+            bool fallbackOnDefault,
+            int32_t* _aidl_return) override;
     binder::Status setRttEnabled(bool enabled) override;
     binder::Status isCallScreenModeSupported(bool* _aidl_return) override;
     binder::Status setDevicesRoleForStrategy(
@@ -274,31 +277,31 @@
     binder::Status getSpatializer(const sp<media::INativeSpatializerCallback>& callback,
             media::GetSpatializerResponse* _aidl_return) override;
     binder::Status canBeSpatialized(
-            const std::optional<media::AudioAttributesInternal>& attr,
+            const std::optional<media::audio::common::AudioAttributes>& attr,
             const std::optional<AudioConfig>& config,
             const std::vector<AudioDevice>& devices,
             bool* _aidl_return) override;
 
-    binder::Status getDirectPlaybackSupport(const media::AudioAttributesInternal& attr,
+    binder::Status getDirectPlaybackSupport(const media::audio::common::AudioAttributes& attr,
                                             const AudioConfig& config,
                                             media::AudioDirectMode* _aidl_return) override;
 
-    binder::Status getDirectProfilesForAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status getDirectProfilesForAttributes(const media::audio::common::AudioAttributes& attr,
                         std::vector<media::audio::common::AudioProfile>* _aidl_return) override;
 
     binder::Status getSupportedMixerAttributes(
             int32_t portId,
             std::vector<media::AudioMixerAttributesInternal>* _aidl_return) override;
     binder::Status setPreferredMixerAttributes(
-            const media::AudioAttributesInternal& attr,
+            const media::audio::common::AudioAttributes& attr,
             int32_t portId,
             int32_t uid,
             const media::AudioMixerAttributesInternal& mixerAttr) override;
     binder::Status getPreferredMixerAttributes(
-            const media::AudioAttributesInternal& attr,
+            const media::audio::common::AudioAttributes& attr,
             int32_t portId,
             std::optional<media::AudioMixerAttributesInternal>* _aidl_return) override;
-    binder::Status clearPreferredMixerAttributes(const media::AudioAttributesInternal& attr,
+    binder::Status clearPreferredMixerAttributes(const media::audio::common::AudioAttributes& attr,
                                                  int32_t portId,
                                                  int32_t uid) override;
 
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 285b354..a4a0cd4 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -78,6 +78,7 @@
         "libaudioclient",
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
+        "libaudiopolicycomponents",
         "libaudiopolicymanagerdefault",
         "libcutils",
         "liblog",
@@ -89,8 +90,6 @@
         "libxml2",
     ],
 
-    static_libs: ["libaudiopolicycomponents"],
-
     header_libs: [
         "libaudiopolicyengine_interface_headers",
         "libaudiopolicymanager_interface_headers",
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 97a1e0d..7a21aa8 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1232,6 +1232,19 @@
     EXPECT_FALSE(isBitPerfect);
     EXPECT_EQ(bitPerfectOutput, output);
 
+    const audio_attributes_t dtmfAttr = {
+            .content_type = AUDIO_CONTENT_TYPE_UNKNOWN,
+            .usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
+    };
+    audio_io_handle_t dtmfOutput = AUDIO_IO_HANDLE_NONE;
+    selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+    portId = AUDIO_PORT_HANDLE_NONE;
+    getOutputForAttr(&selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            48000, AUDIO_OUTPUT_FLAG_NONE, &dtmfOutput, &portId, dtmfAttr,
+            AUDIO_SESSION_NONE, anotherUid, &isBitPerfect);
+    EXPECT_FALSE(isBitPerfect);
+    EXPECT_EQ(bitPerfectOutput, dtmfOutput);
+
     // When configuration matches preferred mixer attributes, which is bit-perfect, but the client
     // is not the owner of preferred mixer attributes, the playback will not be bit-perfect.
     getOutputForAttr(&selectedDeviceId, bitPerfectFormat, bitPerfectChannelMask,