Merge "codec2: change to support multiple fences for single output."
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/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 9783855..2edc0fe 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -749,7 +749,8 @@
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP8)   ? asString_VP8Profile(pl.mProfile) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)  ? asString_HEVCProfile(pl.mProfile) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)   ? asString_VP9Profile(pl.mProfile) :
-                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)   ? asString_AV1Profile(pl.mProfile) :"??";
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)   ? asString_AV1Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION) ? asString_DolbyVisionProfile(pl.mProfile) :"??";
                     const char *niceLevel =
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2) ? asString_MPEG2Level(pl.mLevel) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_H263)  ? asString_H263Level(pl.mLevel) :
@@ -759,6 +760,7 @@
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_HEVC)  ? asString_HEVCTierLevel(pl.mLevel) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)   ? asString_VP9Level(pl.mLevel) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)   ? asString_AV1Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION) ? asString_DolbyVisionLevel(pl.mLevel) :
                         "??";
 
                     list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index ab25c65..cee44b9 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -31,7 +31,33 @@
     ],
 }
 
-cc_binary {
+prebuilt_etc {
+    name: "drmserver.zygote64_32.rc",
+    src: "drmserver.zygote64_32.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "drmserver.zygote64.rc",
+    src: "drmserver.zygote64.rc",
+    sub_dir: "init/hw",
+}
+
+soong_config_module_type {
+    name: "drmserver_cc_binary",
+    module_type: "cc_binary",
+    config_namespace: "ANDROID",
+    bool_variables: ["TARGET_DYNAMIC_64_32_DRMSERVER"],
+    properties: [
+        "compile_multilib",
+        "init_rc",
+        "multilib.lib32.suffix",
+        "multilib.lib64.suffix",
+        "required",
+    ],
+}
+
+drmserver_cc_binary {
     name: "drmserver",
 
     srcs: [
@@ -61,7 +87,27 @@
 
     compile_multilib: "prefer32",
 
-    init_rc: ["drmserver.rc"],
+    soong_config_variables: {
+        TARGET_DYNAMIC_64_32_DRMSERVER: {
+            compile_multilib: "both",
+            multilib: {
+                lib32: {
+                    suffix: "32",
+                },
+                lib64: {
+                    suffix: "64",
+                },
+            },
+            required: [
+                "drmserver.zygote64_32.rc",
+                "drmserver.zygote64.rc",
+            ],
+            init_rc: ["drmserver_dynamic.rc"],
+            conditions_default: {
+                init_rc: ["drmserver.rc"],
+            },
+        },
+    },
 }
 
 cc_fuzz {
@@ -80,7 +126,6 @@
     static_libs: [
         "libmediautils",
         "liblog",
-        "libdl",
         "libdrmframeworkcommon",
         "libselinux",
         "libstagefright_foundation",
@@ -98,4 +143,4 @@
              "android-drm-team@google.com",
          ],
      },
-}
\ No newline at end of file
+}
diff --git a/drm/drmserver/drmserver.zygote64.rc b/drm/drmserver/drmserver.zygote64.rc
new file mode 100644
index 0000000..60cd906
--- /dev/null
+++ b/drm/drmserver/drmserver.zygote64.rc
@@ -0,0 +1,6 @@
+service drm /system/bin/drmserver64
+    disabled
+    class main
+    user drm
+    group drm system inet drmrpc readproc
+    task_profiles ProcessCapacityHigh
diff --git a/drm/drmserver/drmserver.zygote64_32.rc b/drm/drmserver/drmserver.zygote64_32.rc
new file mode 100644
index 0000000..c881acf
--- /dev/null
+++ b/drm/drmserver/drmserver.zygote64_32.rc
@@ -0,0 +1,6 @@
+service drm /system/bin/drmserver32
+    disabled
+    class main
+    user drm
+    group drm system inet drmrpc readproc
+    task_profiles ProcessCapacityHigh
diff --git a/drm/drmserver/drmserver_dynamic.rc b/drm/drmserver/drmserver_dynamic.rc
new file mode 100644
index 0000000..bfaada1
--- /dev/null
+++ b/drm/drmserver/drmserver_dynamic.rc
@@ -0,0 +1,7 @@
+import /system/etc/init/hw/drmserver.${ro.zygote}.rc
+
+on property:drm.service.enabled=true
+    start drm
+
+on property:drm.service.enabled=1
+    start drm
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 0cfd128..17e6e98 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
     };
@@ -1791,6 +1813,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 36f6128..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,9 +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 ec1f75c..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)
@@ -288,6 +290,11 @@
 ConversionResult<media::audio::common::AudioOutputFlags>
 legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
 
+ConversionResult<audio_stream_type_t>
+aidl2legacy_AudioStreamType_audio_stream_type_t(media::audio::common::AudioStreamType aidl);
+ConversionResult<media::audio::common::AudioStreamType>
+legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
+
 // This type is unnamed in the original definition, thus we name it here.
 using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
 ConversionResult<audio_port_config_mix_ext_usecase>
@@ -350,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/AidlConversionNdkCpp.h b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
index 09f1c22..f4822aa 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdkCpp.h
@@ -23,11 +23,13 @@
 #include <aidl/android/media/audio/common/AudioHalEngineConfig.h>
 #include <aidl/android/media/audio/common/AudioMMapPolicyInfo.h>
 #include <aidl/android/media/audio/common/AudioMMapPolicyType.h>
+#include <aidl/android/media/audio/common/AudioMode.h>
 #include <aidl/android/media/audio/common/AudioPort.h>
 #include <android/media/audio/common/AudioFormatDescription.h>
 #include <android/media/audio/common/AudioHalEngineConfig.h>
 #include <android/media/audio/common/AudioMMapPolicyInfo.h>
 #include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioMode.h>
 #include <android/media/audio/common/AudioPort.h>
 #include <media/AidlConversionUtil.h>
 
@@ -43,6 +45,7 @@
 DECLARE_CONVERTERS(android::media::audio::common, AudioHalEngineConfig);
 DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyInfo);
 DECLARE_CONVERTERS(android::media::audio::common, AudioMMapPolicyType);
+DECLARE_CONVERTERS(android::media::audio::common, AudioMode);
 DECLARE_CONVERTERS(android::media::audio::common, AudioPort);
 
 #undef DECLARE_CONVERTERS
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/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index e3db5b4..1e3bfe0 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -50,6 +50,8 @@
 
 int main(int argc __unused, char **argv)
 {
+    ALOGD("%s: starting", __func__);
+    const auto startTime = std::chrono::steady_clock::now();
     // TODO: update with refined parameters
     limitProcessMemory(
         "audio.maxmem", /* "ro.audio.maxmem", property that defines limit */
@@ -144,11 +146,36 @@
             setpgid(0, 0);                      // but if I die first, don't kill my parent
         }
         android::hardware::configureRpcThreadpool(4, false /*callerWillJoin*/);
-        sp<ProcessState> proc(ProcessState::self());
+
+        // Ensure threads for possible callbacks.  Note that get_audio_flinger() does
+        // this automatically when called from AudioPolicy, but we do this anyways here.
+        ProcessState::self()->startThreadPool();
+
+        // Instantiating AudioFlinger (making it public, e.g. through ::initialize())
+        // and then instantiating AudioPolicy (and making it public)
+        // leads to situations where AudioFlinger is accessed remotely before
+        // AudioPolicy is initialized.  Not only might this
+        // cause inaccurate results, but if AudioPolicy has slow audio HAL
+        // initialization, it can cause a TimeCheck abort to occur on an AudioFlinger
+        // call which tries to access AudioPolicy.
+        //
+        // We create AudioFlinger and AudioPolicy locally then make it public to ServiceManager.
+        // This requires both AudioFlinger and AudioPolicy to be in-proc.
+        //
+        const auto af = sp<AudioFlinger>::make();
+        const auto afAdapter = sp<AudioFlingerServerAdapter>::make(af);
+        ALOGD("%s: AudioFlinger created", __func__);
+        ALOGW_IF(AudioSystem::setLocalAudioFlinger(af) != OK,
+                "%s: AudioSystem already has an AudioFlinger instance!", __func__);
+        const auto aps = sp<AudioPolicyService>::make();
+        ALOGD("%s: AudioPolicy created", __func__);
+
+        // Add AudioFlinger and AudioPolicy to ServiceManager.
         sp<IServiceManager> sm = defaultServiceManager();
-        ALOGI("ServiceManager: %p", sm.get());
-        AudioFlinger::instantiate();
-        AudioPolicyService::instantiate();
+        sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME), afAdapter,
+                false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+        sm->addService(String16(AudioPolicyService::getServiceName()), aps,
+                false /* allowIsolated */, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
 
         // AAudioService should only be used in OC-MR1 and later.
         // And only enable the AAudioService if the system MMAP policy explicitly allows it.
@@ -156,7 +183,6 @@
         // If we cannot get audio flinger here, there must be some serious problems. In that case,
         // attempting to call audio flinger on a null pointer could make the process crash
         // and attract attentions.
-        sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
         std::vector<AudioMMapPolicyInfo> policyInfos;
         status_t status = af->getMmapPolicyInfos(
                 AudioMMapPolicyType::DEFAULT, &policyInfos);
@@ -169,11 +195,14 @@
             })) {
             AAudioService::instantiate();
         } else {
-            ALOGD("Do not init aaudio service, status %d, policy info size %zu",
-                  status, policyInfos.size());
+            ALOGD("%s: Do not init aaudio service, status %d, policy info size %zu",
+                  __func__, status, policyInfos.size());
         }
-
-        ProcessState::self()->startThreadPool();
+        const auto endTime = std::chrono::steady_clock::now();
+        using FloatMillis = std::chrono::duration<float, std::milli>;
+        const float timeTaken = std::chrono::duration_cast<FloatMillis>(
+                endTime - startTime).count();
+        ALOGI("%s: initialization done in %.3f ms, joining thread pool", __func__, timeTaken);
         IPCThreadState::self()->joinThreadPool();
     }
 }
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.cpp b/media/codec2/components/flac/C2SoftFlacEnc.cpp
index 182edfb..591d56d 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.cpp
+++ b/media/codec2/components/flac/C2SoftFlacEnc.cpp
@@ -188,12 +188,6 @@
     return onStop();
 }
 
-static void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
-    work->worklets.front()->output.flags = work->input.flags;
-    work->worklets.front()->output.buffers.clear();
-    work->worklets.front()->output.ordinal = work->input.ordinal;
-}
-
 void C2SoftFlacEnc::process(
         const std::unique_ptr<C2Work> &work,
         const std::shared_ptr<C2BlockPool> &pool) {
@@ -245,12 +239,10 @@
         mWroteHeader = true;
     }
 
-    const uint32_t sampleRate = mIntf->getSampleRate();
     const uint32_t channelCount = mIntf->getChannelCount();
     const bool inputFloat = mIntf->getPcmEncodingInfo() == C2Config::PCM_FLOAT;
     const unsigned sampleSize = inputFloat ? sizeof(float) : sizeof(int16_t);
     const unsigned frameSize = channelCount * sampleSize;
-    const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
 
     size_t outCapacity = inSize;
     outCapacity += mBlockSize * frameSize;
@@ -270,6 +262,33 @@
         return;
     }
 
+    class FillWork {
+    public:
+        FillWork(uint32_t flags, C2WorkOrdinalStruct ordinal,
+                 const std::shared_ptr<C2Buffer> &buffer)
+            : mFlags(flags), mOrdinal(ordinal), mBuffer(buffer) {}
+        ~FillWork() = default;
+
+        void operator()(const std::unique_ptr<C2Work> &work) {
+            work->worklets.front()->output.flags = (C2FrameData::flags_t)mFlags;
+            work->worklets.front()->output.buffers.clear();
+            work->worklets.front()->output.ordinal = mOrdinal;
+            work->workletsProcessed = 1u;
+            work->result = C2_OK;
+            if (mBuffer) {
+                work->worklets.front()->output.buffers.push_back(mBuffer);
+            }
+            ALOGV("timestamp = %lld, index = %lld, w/%s buffer",
+                  mOrdinal.timestamp.peekll(), mOrdinal.frameIndex.peekll(),
+                  mBuffer ? "" : "o");
+        }
+
+    private:
+        const uint32_t mFlags;
+        const C2WorkOrdinalStruct mOrdinal;
+        const std::shared_ptr<C2Buffer> mBuffer;
+    };
+
     mEncoderWriteData = true;
     mEncoderReturnedNbBytes = 0;
     size_t inPos = 0;
@@ -308,14 +327,33 @@
         mOutputBlock.reset();
         return;
     }
-    fillEmptyWork(work);
-    if (mEncoderReturnedNbBytes != 0) {
-        std::shared_ptr<C2Buffer> buffer = createLinearBuffer(std::move(mOutputBlock), 0, mEncoderReturnedNbBytes);
-        work->worklets.front()->output.buffers.push_back(buffer);
-        work->worklets.front()->output.ordinal.timestamp = mAnchorTimeStamp + outTimeStamp;
-    } else {
-        ALOGV("encoder process_interleaved returned without data to write");
+
+    // cloneAndSend will create clone of work when more than one encoded frame is produced
+    while (mOutputBuffers.size() > 1) {
+        const OutputBuffer& front = mOutputBuffers.front();
+        C2WorkOrdinalStruct ordinal = work->input.ordinal;
+        ordinal.frameIndex = front.frameIndex;
+        ordinal.timestamp = front.timestampUs;
+        cloneAndSend(work->input.ordinal.frameIndex.peeku(), work,
+                     FillWork(C2FrameData::FLAG_INCOMPLETE, ordinal, front.buffer));
+        mOutputBuffers.pop_front();
     }
+
+    std::shared_ptr<C2Buffer> buffer;
+    C2WorkOrdinalStruct ordinal = work->input.ordinal;
+    if (mOutputBuffers.size() == 1) {
+        const OutputBuffer& front = mOutputBuffers.front();
+        ordinal.frameIndex = front.frameIndex;
+        ordinal.timestamp = front.timestampUs;
+        buffer = front.buffer;
+        mOutputBuffers.pop_front();
+    }
+    // finish the response for the overall transaction.
+    // this includes any final frame that the encoder produced during this request
+    // this response is required even if no data was encoded.
+    FillWork((C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0),
+             ordinal, buffer)(work);
+
     mOutputBlock = nullptr;
     if (eos) {
         mSignalledOutputEos = true;
@@ -349,6 +387,8 @@
     // write encoded data
     C2WriteView wView = mOutputBlock->map().get();
     uint8_t* outData = wView.data();
+    const uint32_t sampleRate = mIntf->getSampleRate();
+    const uint64_t outTimeStamp = mProcessedSamples * 1000000ll / sampleRate;
     ALOGV("writing %zu bytes of encoded data on output", bytes);
     // increment mProcessedSamples to maintain audio synchronization during
     // play back
@@ -359,7 +399,12 @@
         return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
     }
     memcpy(outData + mEncoderReturnedNbBytes, buffer, bytes);
+
+    std::shared_ptr<C2Buffer> c2Buffer =
+        createLinearBuffer(mOutputBlock, mEncoderReturnedNbBytes, bytes);
+    mOutputBuffers.push_back({c2Buffer, mAnchorTimeStamp + outTimeStamp, current_frame});
     mEncoderReturnedNbBytes += bytes;
+
     return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
 }
 
diff --git a/media/codec2/components/flac/C2SoftFlacEnc.h b/media/codec2/components/flac/C2SoftFlacEnc.h
index b3f01d5..a971ab5 100644
--- a/media/codec2/components/flac/C2SoftFlacEnc.h
+++ b/media/codec2/components/flac/C2SoftFlacEnc.h
@@ -79,6 +79,12 @@
     unsigned mHeaderOffset;
     bool mWroteHeader;
     char mHeader[FLAC_HEADER_SIZE];
+    struct OutputBuffer {
+        std::shared_ptr<C2Buffer> buffer;
+        c2_cntr64_t timestampUs;
+        std::uint64_t frameIndex;
+    };
+    std::list<OutputBuffer> mOutputBuffers;
 
     C2_DO_NOT_COPY(C2SoftFlacEnc);
 };
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index e8969dd..3caa258 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -2543,43 +2543,6 @@
 }
 
 void CCodec::initiateReleaseIfStuck() {
-    bool tunneled = false;
-    bool isMediaTypeKnown = false;
-    {
-        static const std::set<std::string> kKnownMediaTypes{
-            MIMETYPE_VIDEO_VP8,
-            MIMETYPE_VIDEO_VP9,
-            MIMETYPE_VIDEO_AV1,
-            MIMETYPE_VIDEO_AVC,
-            MIMETYPE_VIDEO_HEVC,
-            MIMETYPE_VIDEO_MPEG4,
-            MIMETYPE_VIDEO_H263,
-            MIMETYPE_VIDEO_MPEG2,
-            MIMETYPE_VIDEO_RAW,
-            MIMETYPE_VIDEO_DOLBY_VISION,
-
-            MIMETYPE_AUDIO_AMR_NB,
-            MIMETYPE_AUDIO_AMR_WB,
-            MIMETYPE_AUDIO_MPEG,
-            MIMETYPE_AUDIO_AAC,
-            MIMETYPE_AUDIO_QCELP,
-            MIMETYPE_AUDIO_VORBIS,
-            MIMETYPE_AUDIO_OPUS,
-            MIMETYPE_AUDIO_G711_ALAW,
-            MIMETYPE_AUDIO_G711_MLAW,
-            MIMETYPE_AUDIO_RAW,
-            MIMETYPE_AUDIO_FLAC,
-            MIMETYPE_AUDIO_MSGSM,
-            MIMETYPE_AUDIO_AC3,
-            MIMETYPE_AUDIO_EAC3,
-
-            MIMETYPE_IMAGE_ANDROID_HEIC,
-        };
-        Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
-        const std::unique_ptr<Config> &config = *configLocked;
-        tunneled = config->mTunneled;
-        isMediaTypeKnown = (kKnownMediaTypes.count(config->mCodingMediaType) != 0);
-    }
     std::string name;
     bool pendingDeadline = false;
     {
@@ -2591,16 +2554,6 @@
             pendingDeadline = true;
         }
     }
-    if (!tunneled && isMediaTypeKnown && name.empty()) {
-        constexpr std::chrono::steady_clock::duration kWorkDurationThreshold = 3s;
-        std::chrono::steady_clock::duration elapsed = mChannel->elapsed();
-        if (elapsed >= kWorkDurationThreshold) {
-            name = "queue";
-        }
-        if (elapsed > 0s) {
-            pendingDeadline = true;
-        }
-    }
     if (name.empty()) {
         // We're not stuck.
         if (pendingDeadline) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 137507b..91a107f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1586,7 +1586,8 @@
         watcher->inputDelay(inputDelayValue)
                 .pipelineDelay(pipelineDelayValue)
                 .outputDelay(outputDelayValue)
-                .smoothnessFactor(kSmoothnessFactor);
+                .smoothnessFactor(kSmoothnessFactor)
+                .tunneled(mTunneled);
         watcher->flush();
     }
 
@@ -1989,6 +1990,7 @@
             newInputDelay.value_or(input->inputDelay) +
             newPipelineDelay.value_or(input->pipelineDelay) +
             kSmoothnessFactor;
+        input->inputDelay = newInputDelay.value_or(input->inputDelay);
         if (input->buffers->isArrayMode()) {
             if (input->numSlots >= newNumSlots) {
                 input->numExtraSlots = 0;
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 0253815..f185a1c 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -619,30 +619,30 @@
         .limitTo(D::OUTPUT & D::READ));
 
     deprecated(ConfigMapper(KEY_HDR10_PLUS_INFO, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO, "value")
-        .limitTo(D::VIDEO & D::PARAM & D::INPUT));
+        .limitTo(D::VIDEO & D::PARAM & D::INPUT & (D::CONFIG | D::PARAM)));
 
     deprecated(ConfigMapper(KEY_HDR10_PLUS_INFO, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO, "value")
-        .limitTo(D::VIDEO & D::OUTPUT));
+        .limitTo(D::VIDEO & D::OUTPUT & D::READ));
 
     add(ConfigMapper(
             std::string(C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO) + ".type",
             C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO, "type")
-        .limitTo(D::VIDEO & D::PARAM & D::INPUT));
+        .limitTo(D::VIDEO & D::PARAM & D::INPUT & (D::CONFIG | D::PARAM)));
 
     add(ConfigMapper(
             std::string(C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO) + ".data",
             C2_PARAMKEY_INPUT_HDR_DYNAMIC_INFO, "data")
-        .limitTo(D::VIDEO & D::PARAM & D::INPUT));
+        .limitTo(D::VIDEO & D::PARAM & D::INPUT & (D::CONFIG | D::PARAM)));
 
     add(ConfigMapper(
             std::string(C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO) + ".type",
             C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO, "type")
-        .limitTo(D::VIDEO & D::OUTPUT));
+        .limitTo(D::VIDEO & D::OUTPUT & D::READ));
 
     add(ConfigMapper(
             std::string(C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO) + ".data",
             C2_PARAMKEY_OUTPUT_HDR_DYNAMIC_INFO, "data")
-        .limitTo(D::VIDEO & D::OUTPUT));
+        .limitTo(D::VIDEO & D::OUTPUT & D::READ));
 
     add(ConfigMapper(C2_PARAMKEY_TEMPORAL_LAYERING, C2_PARAMKEY_TEMPORAL_LAYERING, "")
         .limitTo(D::ENCODER & D::VIDEO & D::OUTPUT));
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 8f0f1c9..3eb2e63 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -478,19 +478,56 @@
                 mInitCheck = NO_INIT;
                 return;
             case C2PlanarLayout::TYPE_RGB:
-                ALOGD("Converter: unrecognized color format "
-                        "(client %d component %d) for RGB layout",
-                        mClientColorFormat, mComponentColorFormat);
-                mInitCheck = NO_INIT;
+                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
                 // TODO: support MediaImage layout
-                return;
+                switch (mClientColorFormat) {
+                    case COLOR_FormatSurface:
+                    case COLOR_FormatRGBFlexible:
+                    case COLOR_Format24bitBGR888:
+                    case COLOR_Format24bitRGB888:
+                        ALOGD("Converter: accept color format "
+                                "(client %d component %d) for RGB layout",
+                                mClientColorFormat, mComponentColorFormat);
+                        break;
+                    default:
+                        ALOGD("Converter: unrecognized color format "
+                                "(client %d component %d) for RGB layout",
+                                mClientColorFormat, mComponentColorFormat);
+                        mInitCheck = BAD_VALUE;
+                        return;
+                }
+                if (layout.numPlanes != 3) {
+                    ALOGD("Converter: %d planes for RGB layout", layout.numPlanes);
+                    mInitCheck = BAD_VALUE;
+                    return;
+                }
+                break;
             case C2PlanarLayout::TYPE_RGBA:
-                ALOGD("Converter: unrecognized color format "
-                        "(client %d component %d) for RGBA layout",
-                        mClientColorFormat, mComponentColorFormat);
-                mInitCheck = NO_INIT;
+                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
                 // TODO: support MediaImage layout
-                return;
+                switch (mClientColorFormat) {
+                    case COLOR_FormatSurface:
+                    case COLOR_FormatRGBAFlexible:
+                    case COLOR_Format32bitABGR8888:
+                    case COLOR_Format32bitARGB8888:
+                    case COLOR_Format32bitBGRA8888:
+                        ALOGD("Converter: accept color format "
+                                "(client %d component %d) for RGBA layout",
+                                mClientColorFormat, mComponentColorFormat);
+                        break;
+                    default:
+                        ALOGD("Converter: unrecognized color format "
+                                "(client %d component %d) for RGBA layout",
+                                mClientColorFormat, mComponentColorFormat);
+                        mInitCheck = BAD_VALUE;
+                        return;
+                }
+                if (layout.numPlanes != 4) {
+                    ALOGD("Converter: %d planes for RGBA layout", layout.numPlanes);
+                    mInitCheck = BAD_VALUE;
+                    return;
+                }
+                break;
             default:
                 mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
                 if (layout.numPlanes == 1) {
diff --git a/media/codec2/sfplugin/PipelineWatcher.cpp b/media/codec2/sfplugin/PipelineWatcher.cpp
index bc9197c..fa70a28 100644
--- a/media/codec2/sfplugin/PipelineWatcher.cpp
+++ b/media/codec2/sfplugin/PipelineWatcher.cpp
@@ -45,6 +45,11 @@
     return *this;
 }
 
+PipelineWatcher &PipelineWatcher::tunneled(bool value) {
+    mTunneled = value;
+    return *this;
+}
+
 void PipelineWatcher::onWorkQueued(
         uint64_t frameIndex,
         std::vector<std::shared_ptr<C2Buffer>> &&buffers,
@@ -87,8 +92,13 @@
     ALOGV("onWorkDone(frameIndex=%llu)", (unsigned long long)frameIndex);
     auto it = mFramesInPipeline.find(frameIndex);
     if (it == mFramesInPipeline.end()) {
-        ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
-              (unsigned long long)frameIndex);
+        if (!mTunneled) {
+            ALOGD("onWorkDone: frameIndex not found (%llu); ignored",
+                  (unsigned long long)frameIndex);
+        } else {
+            ALOGV("onWorkDone: frameIndex not found (%llu); ignored",
+                  (unsigned long long)frameIndex);
+        }
         return;
     }
     (void)mFramesInPipeline.erase(it);
diff --git a/media/codec2/sfplugin/PipelineWatcher.h b/media/codec2/sfplugin/PipelineWatcher.h
index 1e23147..b29c7cd 100644
--- a/media/codec2/sfplugin/PipelineWatcher.h
+++ b/media/codec2/sfplugin/PipelineWatcher.h
@@ -37,7 +37,8 @@
         : mInputDelay(0),
           mPipelineDelay(0),
           mOutputDelay(0),
-          mSmoothnessFactor(0) {}
+          mSmoothnessFactor(0),
+          mTunneled(false) {}
     ~PipelineWatcher() = default;
 
     /**
@@ -65,6 +66,12 @@
     PipelineWatcher &smoothnessFactor(uint32_t value);
 
     /**
+     * \param value the new tunneled value
+     * \return  this object
+     */
+    PipelineWatcher &tunneled(bool value);
+
+    /**
      * Client queued a work item to the component.
      *
      * \param frameIndex  input frame index of this work
@@ -122,6 +129,7 @@
     uint32_t mPipelineDelay;
     uint32_t mOutputDelay;
     uint32_t mSmoothnessFactor;
+    bool mTunneled;
 
     struct Frame {
         Frame(std::vector<std::shared_ptr<C2Buffer>> &&b,
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 dc7afdb..9664271 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -48,7 +48,7 @@
 cc_library {
     name: "libaudiopolicy",
     srcs: [
-        "AudioAttributes.cpp",
+        "VolumeGroupAttributes.cpp",
         "AudioPolicy.cpp",
         "AudioProductStrategy.cpp",
         "AudioVolumeGroup.cpp",
@@ -281,15 +281,15 @@
     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",
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
         "aidl/android/media/AudioPatchFw.aidl",
+        "aidl/android/media/AudioPolicyConfig.aidl",
         "aidl/android/media/AudioPortFw.aidl",
         "aidl/android/media/AudioPortSys.aidl",
         "aidl/android/media/AudioPortConfigFw.aidl",
diff --git a/media/libaudioclient/AudioProductStrategy.cpp b/media/libaudioclient/AudioProductStrategy.cpp
index ecd423a..d9fd58c 100644
--- a/media/libaudioclient/AudioProductStrategy.cpp
+++ b/media/libaudioclient/AudioProductStrategy.cpp
@@ -18,7 +18,7 @@
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 #include <media/AudioProductStrategy.h>
-#include <media/AudioAttributes.h>
+#include <media/VolumeGroupAttributes.h>
 #include <media/PolicyAidlConversion.h>
 
 namespace android {
@@ -42,8 +42,8 @@
     aidl.name = legacy.getName();
     aidl.audioAttributes = VALUE_OR_RETURN(
             convertContainer<std::vector<media::AudioAttributesEx>>(
-                    legacy.getAudioAttributes(),
-                    legacy2aidl_AudioAttributes_AudioAttributesEx));
+                    legacy.getVolumeGroupAttributes(),
+                    legacy2aidl_VolumeGroupAttributes_AudioAttributesEx));
     aidl.id = VALUE_OR_RETURN(legacy2aidl_product_strategy_t_int32_t(legacy.getId()));
     return aidl;
 }
@@ -53,32 +53,57 @@
     return AudioProductStrategy(
             aidl.name,
             VALUE_OR_RETURN(
-                    convertContainer<std::vector<AudioAttributes>>(
+                    convertContainer<std::vector<VolumeGroupAttributes>>(
                             aidl.audioAttributes,
-                            aidl2legacy_AudioAttributesEx_AudioAttributes)),
+                            aidl2legacy_AudioAttributesEx_VolumeGroupAttributes)),
             VALUE_OR_RETURN(aidl2legacy_int32_t_product_strategy_t(aidl.id)));
 }
 
 // Keep in sync with android/media/audiopolicy/AudioProductStrategy#attributeMatches
-bool AudioProductStrategy::attributesMatches(const audio_attributes_t refAttributes,
-                                        const audio_attributes_t clientAttritubes)
+int AudioProductStrategy::attributesMatchesScore(const audio_attributes_t refAttributes,
+                                                 const audio_attributes_t clientAttritubes)
 {
+    if (refAttributes == clientAttritubes) {
+        return MATCH_EQUALS;
+    }
     if (refAttributes == AUDIO_ATTRIBUTES_INITIALIZER) {
         // The default product strategy is the strategy that holds default attributes by convention.
         // All attributes that fail to match will follow the default strategy for routing.
-        // Choosing the default must be done as a fallback, the attributes match shall not
-        // select the default.
-        return false;
+        // Choosing the default must be done as a fallback,so return a default (zero) score to
+        // allow identify the fallback.
+        return MATCH_ON_DEFAULT_SCORE;
     }
-    return ((refAttributes.usage == AUDIO_USAGE_UNKNOWN) ||
-            (clientAttritubes.usage == refAttributes.usage)) &&
-            ((refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) ||
-             (clientAttritubes.content_type == refAttributes.content_type)) &&
-            ((refAttributes.flags == AUDIO_FLAG_NONE) ||
-             (clientAttritubes.flags != AUDIO_FLAG_NONE &&
-            (clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) &&
-            ((strlen(refAttributes.tags) == 0) ||
-             (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0));
+    int score = MATCH_ON_DEFAULT_SCORE;
+    if (refAttributes.usage == AUDIO_USAGE_UNKNOWN) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if (clientAttritubes.usage == refAttributes.usage) {
+        score |= MATCH_ON_USAGE_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    if (refAttributes.content_type == AUDIO_CONTENT_TYPE_UNKNOWN) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if (clientAttritubes.content_type == refAttributes.content_type) {
+        score |= MATCH_ON_CONTENT_TYPE_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    if (strlen(refAttributes.tags) == 0) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if (std::strcmp(clientAttritubes.tags, refAttributes.tags) == 0) {
+        score |= MATCH_ON_TAGS_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    if (refAttributes.flags == AUDIO_FLAG_NONE) {
+        score |= MATCH_ON_DEFAULT_SCORE;
+    } else if ((clientAttritubes.flags != AUDIO_FLAG_NONE)
+            && ((clientAttritubes.flags & refAttributes.flags) == refAttributes.flags)) {
+        score |= MATCH_ON_FLAGS_SCORE;
+    } else {
+        return NO_MATCH;
+    }
+    return score;
 }
 
 } // namespace android
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 7c7b65b..d58181c 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -81,7 +81,7 @@
 // Binder for the AudioFlinger service that's passed to this client process from the system server.
 // This allows specific isolated processes to access the audio system. Currently used only for the
 // HotwordDetectionService.
-sp<IBinder> gAudioFlingerBinder = nullptr;
+static sp<IBinder> gAudioFlingerBinder = nullptr;
 
 void AudioSystem::setAudioFlingerBinder(const sp<IBinder>& audioFlinger) {
     if (audioFlinger->getInterfaceDescriptor() != media::IAudioFlingerService::descriptor) {
@@ -97,6 +97,15 @@
     gAudioFlingerBinder = audioFlinger;
 }
 
+static sp<IAudioFlinger> gLocalAudioFlinger; // set if we are local.
+
+status_t AudioSystem::setLocalAudioFlinger(const sp<IAudioFlinger>& af) {
+    Mutex::Autolock _l(gLock);
+    if (gAudioFlinger != nullptr) return INVALID_OPERATION;
+    gLocalAudioFlinger = af;
+    return OK;
+}
+
 // establish binder interface to AudioFlinger service
 const sp<IAudioFlinger> AudioSystem::get_audio_flinger() {
     sp<IAudioFlinger> af;
@@ -104,7 +113,19 @@
     bool reportNoError = false;
     {
         Mutex::Autolock _l(gLock);
-        if (gAudioFlinger == 0) {
+        if (gAudioFlinger != nullptr) {
+            return gAudioFlinger;
+        }
+
+        if (gAudioFlingerClient == nullptr) {
+            gAudioFlingerClient = sp<AudioFlingerClient>::make();
+        } else {
+            reportNoError = true;
+        }
+
+        if (gLocalAudioFlinger != nullptr) {
+            gAudioFlinger = gLocalAudioFlinger;
+        } else {
             sp<IBinder> binder;
             if (gAudioFlingerBinder != nullptr) {
                 binder = gAudioFlingerBinder;
@@ -112,32 +133,24 @@
                 sp<IServiceManager> sm = defaultServiceManager();
                 do {
                     binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
-                    if (binder != 0)
-                        break;
+                    if (binder != nullptr) break;
                     ALOGW("AudioFlinger not published, waiting...");
                     usleep(500000); // 0.5 s
                 } while (true);
             }
-            if (gAudioFlingerClient == NULL) {
-                gAudioFlingerClient = new AudioFlingerClient();
-            } else {
-                reportNoError = true;
-            }
             binder->linkToDeath(gAudioFlingerClient);
-            gAudioFlinger = new AudioFlingerClientAdapter(
-                    interface_cast<media::IAudioFlingerService>(binder));
-            LOG_ALWAYS_FATAL_IF(gAudioFlinger == 0);
-            afc = gAudioFlingerClient;
-            // Make sure callbacks can be received by gAudioFlingerClient
-            ProcessState::self()->startThreadPool();
+            const auto afs = interface_cast<media::IAudioFlingerService>(binder);
+            LOG_ALWAYS_FATAL_IF(afs == nullptr);
+            gAudioFlinger = sp<AudioFlingerClientAdapter>::make(afs);
         }
+        afc = gAudioFlingerClient;
         af = gAudioFlinger;
+        // Make sure callbacks can be received by gAudioFlingerClient
+        ProcessState::self()->startThreadPool();
     }
-    if (afc != 0) {
-        int64_t token = IPCThreadState::self()->clearCallingIdentity();
-        af->registerClient(afc);
-        IPCThreadState::self()->restoreCallingIdentity(token);
-    }
+    const int64_t token = IPCThreadState::self()->clearCallingIdentity();
+    af->registerClient(afc);
+    IPCThreadState::self()->restoreCallingIdentity(token);
     if (reportNoError) reportError(NO_ERROR);
     return af;
 }
@@ -1051,8 +1064,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*/));
@@ -1144,8 +1157,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));
@@ -1261,8 +1274,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));
@@ -1276,8 +1289,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;
@@ -1291,8 +1304,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)));
@@ -1304,8 +1317,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)));
@@ -1328,7 +1341,7 @@
     return result.value_or(PRODUCT_STRATEGY_NONE);
 }
 
-status_t AudioSystem::getDevicesForAttributes(const AudioAttributes& aa,
+status_t AudioSystem::getDevicesForAttributes(const audio_attributes_t& aa,
                                               AudioDeviceTypeAddrVector* devices,
                                               bool forVolume) {
     if (devices == nullptr) {
@@ -1337,8 +1350,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesEx aaAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioAttributes_AudioAttributesEx(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)));
@@ -1856,8 +1869,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)));
@@ -2094,7 +2107,7 @@
     AudioProductStrategyVector strategies;
     listAudioProductStrategies(strategies);
     for (const auto& strategy : strategies) {
-        auto attrVect = strategy.getAudioAttributes();
+        auto attrVect = strategy.getVolumeGroupAttributes();
         auto iter = std::find_if(begin(attrVect), end(attrVect), [&stream](const auto& attributes) {
             return attributes.getStreamType() == stream;
         });
@@ -2108,7 +2121,7 @@
 
 audio_stream_type_t AudioSystem::attributesToStreamType(const audio_attributes_t& attr) {
     product_strategy_t psId;
-    status_t ret = AudioSystem::getProductStrategyFromAudioAttributes(AudioAttributes(attr), psId);
+    status_t ret = AudioSystem::getProductStrategyFromAudioAttributes(attr, psId);
     if (ret != NO_ERROR) {
         ALOGE("no strategy found for attributes %s", toString(attr).c_str());
         return AUDIO_STREAM_MUSIC;
@@ -2117,10 +2130,9 @@
     listAudioProductStrategies(strategies);
     for (const auto& strategy : strategies) {
         if (strategy.getId() == psId) {
-            auto attrVect = strategy.getAudioAttributes();
+            auto attrVect = strategy.getVolumeGroupAttributes();
             auto iter = std::find_if(begin(attrVect), end(attrVect), [&attr](const auto& refAttr) {
-                return AudioProductStrategy::attributesMatches(
-                        refAttr.getAttributes(), attr);
+                return refAttr.matchesScore(attr) > 0;
             });
             if (iter != end(attrVect)) {
                 return iter->getStreamType();
@@ -2138,14 +2150,14 @@
     return AUDIO_STREAM_MUSIC;
 }
 
-status_t AudioSystem::getProductStrategyFromAudioAttributes(const AudioAttributes& aa,
+status_t AudioSystem::getProductStrategyFromAudioAttributes(const audio_attributes_t& aa,
                                                             product_strategy_t& productStrategy,
                                                             bool fallbackOnDefault) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesEx aaAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioAttributes_AudioAttributesEx(aa));
+    media::audio::common::AudioAttributes aaAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(aa));
     int32_t productStrategyAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -2168,14 +2180,14 @@
     return OK;
 }
 
-status_t AudioSystem::getVolumeGroupFromAudioAttributes(const AudioAttributes& aa,
+status_t AudioSystem::getVolumeGroupFromAudioAttributes(const audio_attributes_t &aa,
                                                         volume_group_t& volumeGroup,
                                                         bool fallbackOnDefault) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioAttributesEx aaAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioAttributes_AudioAttributesEx(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)));
@@ -2363,8 +2375,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(
@@ -2387,8 +2399,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*/));
 
@@ -2411,8 +2423,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(
@@ -2467,6 +2479,14 @@
     return af->supportsBluetoothVariableLatency(support);
 }
 
+status_t AudioSystem::getAudioPolicyConfig(media::AudioPolicyConfig *config) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == nullptr) {
+        return PERMISSION_DENIED;
+    }
+    return af->getAudioPolicyConfig(config);
+}
+
 class CaptureStateListenerImpl : public media::BnCaptureStateListener,
                                  public IBinder::DeathRecipient {
 public:
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 12f5013..5bf6b656 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -175,8 +175,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 ab95246..c4ca5b9 100644
--- a/media/libaudioclient/AudioVolumeGroup.cpp
+++ b/media/libaudioclient/AudioVolumeGroup.cpp
@@ -23,7 +23,6 @@
 
 #include <media/AidlConversion.h>
 #include <media/AudioVolumeGroup.h>
-#include <media/AudioAttributes.h>
 #include <media/PolicyAidlConversion.h>
 
 namespace android {
@@ -50,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));
@@ -66,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 756597e..00ef0a4 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*/));
@@ -144,7 +144,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));
@@ -165,7 +165,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));
@@ -866,6 +866,16 @@
     return NO_ERROR;
 }
 
+status_t AudioFlingerClientAdapter::getAudioPolicyConfig(media::AudioPolicyConfig *config) {
+    if (config == nullptr) {
+        return BAD_VALUE;
+    }
+
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getAudioPolicyConfig(config)));
+
+    return NO_ERROR;
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // AudioFlingerServerAdapter
 AudioFlingerServerAdapter::AudioFlingerServerAdapter(
@@ -1399,4 +1409,8 @@
     return Status::fromStatusT(mDelegate->supportsBluetoothVariableLatency(support));
 }
 
+Status AudioFlingerServerAdapter::getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) {
+    return Status::fromStatusT(mDelegate->getAudioPolicyConfig(_aidl_return));
+}
+
 } // namespace android
diff --git a/media/libaudioclient/AudioAttributes.cpp b/media/libaudioclient/VolumeGroupAttributes.cpp
similarity index 63%
rename from media/libaudioclient/AudioAttributes.cpp
rename to media/libaudioclient/VolumeGroupAttributes.cpp
index 260c06c..938e574 100644
--- a/media/libaudioclient/AudioAttributes.cpp
+++ b/media/libaudioclient/VolumeGroupAttributes.cpp
@@ -14,48 +14,53 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "AudioAttributes"
+#define LOG_TAG "VolumeGroupAttributes"
 //#define LOG_NDEBUG 0
 #include <utils/Log.h>
 
 #include <binder/Parcel.h>
 
 #include <media/AidlConversion.h>
-#include <media/AudioAttributes.h>
+#include <media/AudioProductStrategy.h>
+#include <media/VolumeGroupAttributes.h>
 #include <media/PolicyAidlConversion.h>
 
 namespace android {
 
-status_t AudioAttributes::readFromParcel(const Parcel* parcel) {
+int VolumeGroupAttributes::matchesScore(const audio_attributes_t &attributes) const {
+    return AudioProductStrategy::attributesMatchesScore(mAttributes, attributes);
+}
+
+status_t VolumeGroupAttributes::readFromParcel(const Parcel* parcel) {
     media::AudioAttributesEx aidl;
     RETURN_STATUS_IF_ERROR(aidl.readFromParcel(parcel));
-    *this = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioAttributesEx_AudioAttributes(aidl));
+    *this = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(aidl));
     return OK;
 }
 
-status_t AudioAttributes::writeToParcel(Parcel* parcel) const {
+status_t VolumeGroupAttributes::writeToParcel(Parcel* parcel) const {
     media::AudioAttributesEx aidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioAttributes_AudioAttributesEx(*this));
+            legacy2aidl_VolumeGroupAttributes_AudioAttributesEx(*this));
     return aidl.writeToParcel(parcel);
 }
 
 ConversionResult<media::AudioAttributesEx>
-legacy2aidl_AudioAttributes_AudioAttributesEx(const AudioAttributes& legacy) {
+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()));
     return aidl;
 }
 
-ConversionResult<AudioAttributes>
-aidl2legacy_AudioAttributesEx_AudioAttributes(const media::AudioAttributesEx& aidl) {
-    return AudioAttributes(VALUE_OR_RETURN(aidl2legacy_int32_t_volume_group_t(aidl.groupId)),
+ConversionResult<VolumeGroupAttributes>
+aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(const media::AudioAttributesEx& aidl) {
+    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/services/audioflinger/StateQueueInstantiations.cpp b/media/libaudioclient/aidl/android/media/AudioHwModule.aidl
similarity index 60%
rename from services/audioflinger/StateQueueInstantiations.cpp
rename to media/libaudioclient/aidl/android/media/AudioHwModule.aidl
index 6f4505e..9251400 100644
--- a/services/audioflinger/StateQueueInstantiations.cpp
+++ b/media/libaudioclient/aidl/android/media/AudioHwModule.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -14,16 +14,18 @@
  * limitations under the License.
  */
 
-#include "Configuration.h"
-#include "FastMixerState.h"
-#include "FastCaptureState.h"
-#include "StateQueue.h"
+package android.media;
 
-// FIXME hack for gcc
+import android.media.audio.common.AudioPort;
+import android.media.AudioRoute;
 
-namespace android {
-
-template class StateQueue<FastMixerState>;      // typedef FastMixerStateQueue
-template class StateQueue<FastCaptureState>;    // typedef FastCaptureStateQueue
-
+/*
+ * A representation of a HAL module configuration.
+ * {@hide}
+ */
+parcelable AudioHwModule {
+    int /* audio_module_handle_t */ handle;
+    @utf8InCpp String name;
+    AudioPort[] ports;
+    AudioRoute[] routes;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl
new file mode 100644
index 0000000..87767c2
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioPolicyConfig.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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;
+
+import android.media.AudioHwModule;
+import android.media.SurroundSoundConfig;
+import android.media.audio.common.AudioHalEngineConfig;
+import android.media.audio.common.AudioMode;
+
+/*
+ * Audio policy configuration. Functionally replaces the APM XML file.
+ * {@hide}
+ */
+parcelable AudioPolicyConfig {
+    AudioHwModule[] modules;
+    AudioMode[] supportedModes;
+    SurroundSoundConfig surroundSoundConfig;
+    AudioHalEngineConfig engineConfig;
+}
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/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index b722d14..1f4b3a9 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.media.AudioPatchFw;
+import android.media.AudioPolicyConfig;
 import android.media.AudioPortFw;
 import android.media.AudioPortConfigFw;
 import android.media.AudioUniqueIdUse;
@@ -270,6 +271,12 @@
      */
     boolean isBluetoothVariableLatencyEnabled();
 
+    /**
+     * Only implemented for AIDL. Provides the APM configuration which
+     * used to be in the XML file.
+     */
+    AudioPolicyConfig getAudioPolicyConfig();
+
     // When adding a new method, please review and update
     // IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
     // AudioFlinger.cpp AudioFlinger::onTransactWrapper()
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index fb87042..5c1a92f 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.AudioOffloadMode;
@@ -42,6 +40,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;
@@ -84,7 +83,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,
@@ -97,7 +96,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,
@@ -124,20 +123,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 AudioAttributesEx attr, boolean forVolume);
+    AudioDevice[] getDevicesForAttributes(in AudioAttributes attr, boolean forVolume);
 
     int /* audio_io_handle_t */ getOutputForEffect(in EffectDescriptor desc);
 
@@ -199,7 +198,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.
@@ -271,7 +270,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);
 
@@ -322,11 +321,11 @@
     boolean isUltrasoundSupported();
 
     AudioProductStrategy[] listAudioProductStrategies();
-    int /* product_strategy_t */ getProductStrategyFromAudioAttributes(in AudioAttributesEx aa,
-                                                                       boolean fallbackOnDefault);
+    int /* product_strategy_t */ getProductStrategyFromAudioAttributes(
+            in AudioAttributes aa, boolean fallbackOnDefault);
 
     AudioVolumeGroup[] listAudioVolumeGroups();
-    int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributesEx aa,
+    int /* volume_group_t */ getVolumeGroupFromAudioAttributes(in AudioAttributes aa,
                                                                boolean fallbackOnDefault);
 
     void setRttEnabled(boolean enabled);
@@ -384,21 +383,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);
 
     // When adding a new method, please review and update
     // AudioPolicyService.cpp AudioPolicyService::onTransact()
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 5bd0114..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>
@@ -72,11 +70,6 @@
         media::audio::common::AudioPortDeviceExt* aidl,
         media::AudioPortDeviceExtSys* aidlDeviceExt);
 
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
-        media::audio::common::AudioStreamType aidl);
-ConversionResult<media::audio::common::AudioStreamType>
-legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
-
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
         const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
         const media::AudioPortMixExtSys& aidlMixExt);
@@ -110,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/include/media/AudioProductStrategy.h b/media/libaudioclient/include/media/AudioProductStrategy.h
index b55b506..fcbb019 100644
--- a/media/libaudioclient/include/media/AudioProductStrategy.h
+++ b/media/libaudioclient/include/media/AudioProductStrategy.h
@@ -20,7 +20,7 @@
 #include <android/media/AudioProductStrategy.h>
 #include <media/AidlConversionUtil.h>
 #include <media/AudioCommonTypes.h>
-#include <media/AudioAttributes.h>
+#include <media/VolumeGroupAttributes.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include <binder/Parcelable.h>
@@ -31,34 +31,53 @@
 {
 public:
     AudioProductStrategy() {}
-    AudioProductStrategy(const std::string &name, const std::vector<AudioAttributes> &attributes,
+    AudioProductStrategy(const std::string &name,
+                         const std::vector<VolumeGroupAttributes> &attributes,
                          product_strategy_t id) :
-        mName(name), mAudioAttributes(attributes), mId(id) {}
+        mName(name), mVolumeGroupAttributes(attributes), mId(id) {}
 
     const std::string &getName() const { return mName; }
-    std::vector<AudioAttributes> getAudioAttributes() const { return mAudioAttributes; }
+    std::vector<VolumeGroupAttributes> getVolumeGroupAttributes() const {
+        return mVolumeGroupAttributes;
+    }
     product_strategy_t getId() const { return mId; }
 
     status_t readFromParcel(const Parcel *parcel) override;
     status_t writeToParcel(Parcel *parcel) const override;
 
     /**
-     * @brief attributesMatches: checks if client attributes matches with a reference attributes
-     * "matching" means the usage shall match if reference attributes has a defined usage, AND
-     * content type shall match if reference attributes has a defined content type AND
+     * @brief attributesMatchesScore: checks if client attributes matches with a reference
+     * attributes "matching" means the usage shall match if reference attributes has a defined
+     * usage, AND content type shall match if reference attributes has a defined content type AND
      * flags shall match if reference attributes has defined flags AND
      * tags shall match if reference attributes has defined tags.
-     * Reference attributes "default" shall not be considered as a "true" case. This convention
+     * Reference attributes "default" shall be considered as a weak match case. This convention
      * is used to identify the default strategy.
      * @param refAttributes to be considered
      * @param clientAttritubes to be considered
-     * @return true if matching, false otherwise
+     * @return {@code INVALID_SCORE} if not matching, {@code MATCH_ON_DEFAULT_SCORE} if matching
+     * to default strategy, non zero positive score if matching a strategy.
      */
+    static int attributesMatchesScore(const audio_attributes_t refAttributes,
+                                      const audio_attributes_t clientAttritubes);
+
     static bool attributesMatches(const audio_attributes_t refAttributes,
-                                  const audio_attributes_t clientAttritubes);
+                                      const audio_attributes_t clientAttritubes) {
+        return attributesMatchesScore(refAttributes, clientAttritubes) > 0;
+    }
+
+    static const int MATCH_ON_TAGS_SCORE = 1 << 3;
+    static const int MATCH_ON_FLAGS_SCORE = 1 << 2;
+    static const int MATCH_ON_USAGE_SCORE = 1 << 1;
+    static const int MATCH_ON_CONTENT_TYPE_SCORE = 1 << 0;
+    static const int MATCH_ON_DEFAULT_SCORE = 0;
+    static const int MATCH_EQUALS = MATCH_ON_TAGS_SCORE | MATCH_ON_FLAGS_SCORE
+            | MATCH_ON_USAGE_SCORE | MATCH_ON_CONTENT_TYPE_SCORE;
+    static const int NO_MATCH = -1;
+
 private:
     std::string mName;
-    std::vector<AudioAttributes> mAudioAttributes;
+    std::vector<VolumeGroupAttributes> mVolumeGroupAttributes;
     product_strategy_t mId;
 };
 
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 3e3b79c..25111d7 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -23,6 +23,7 @@
 #include <vector>
 
 #include <android/content/AttributionSourceState.h>
+#include <android/media/AudioPolicyConfig.h>
 #include <android/media/AudioPortFw.h>
 #include <android/media/AudioVibratorInfo.h>
 #include <android/media/BnAudioFlingerClient.h>
@@ -166,6 +167,10 @@
     // HotwordDetectionService.
     static void setAudioFlingerBinder(const sp<IBinder>& audioFlinger);
 
+    // Sets a local AudioFlinger interface to be used by AudioSystem.
+    // This is used by audioserver main() to avoid binder AIDL translation.
+    static status_t setLocalAudioFlinger(const sp<IAudioFlinger>& af);
+
     // helper function to obtain AudioFlinger service handle
     static const sp<IAudioFlinger> get_audio_flinger();
 
@@ -335,7 +340,7 @@
     static status_t getMinVolumeIndexForAttributes(const audio_attributes_t &attr, int &index);
 
     static product_strategy_t getStrategyForStream(audio_stream_type_t stream);
-    static status_t getDevicesForAttributes(const AudioAttributes &aa,
+    static status_t getDevicesForAttributes(const audio_attributes_t &aa,
                                             AudioDeviceTypeAddrVector *devices,
                                             bool forVolume);
 
@@ -462,7 +467,7 @@
 
     static status_t listAudioProductStrategies(AudioProductStrategyVector &strategies);
     static status_t getProductStrategyFromAudioAttributes(
-            const AudioAttributes &aa, product_strategy_t &productStrategy,
+            const audio_attributes_t &aa, product_strategy_t &productStrategy,
             bool fallbackOnDefault = true);
 
     static audio_attributes_t streamTypeToAttributes(audio_stream_type_t stream);
@@ -471,7 +476,8 @@
     static status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups);
 
     static status_t getVolumeGroupFromAudioAttributes(
-            const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault = true);
+            const audio_attributes_t &aa, volume_group_t &volumeGroup,
+            bool fallbackOnDefault = true);
 
     static status_t setRttEnabled(bool enabled);
 
@@ -588,6 +594,8 @@
 
     static status_t supportsBluetoothVariableLatency(bool *support);
 
+    static status_t getAudioPolicyConfig(media::AudioPolicyConfig *config);
+
     // A listener for capture state changes.
     class CaptureStateListener : public virtual RefBase {
     public:
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c43769b..1064e59 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -374,6 +374,8 @@
     virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
 
     virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
+
+    virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) = 0;
 };
 
 /**
@@ -485,6 +487,7 @@
     status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
     status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
     status_t supportsBluetoothVariableLatency(bool* support) override;
+    status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) override;
 
 private:
     const sp<media::IAudioFlingerService> mDelegate;
@@ -583,6 +586,8 @@
                     media::BnAudioFlingerService::TRANSACTION_isBluetoothVariableLatencyEnabled,
             SUPPORTS_BLUETOOTH_VARIABLE_LATENCY =
                     media::BnAudioFlingerService::TRANSACTION_supportsBluetoothVariableLatency,
+            GET_AUDIO_POLICY_CONFIG =
+                    media::BnAudioFlingerService::TRANSACTION_getAudioPolicyConfig,
         };
 
     protected:
@@ -713,6 +718,7 @@
     Status setBluetoothVariableLatencyEnabled(bool enabled) override;
     Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
     Status supportsBluetoothVariableLatency(bool* support) override;
+    Status getAudioPolicyConfig(media::AudioPolicyConfig* _aidl_return) override;
 private:
     const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
 };
diff --git a/media/libaudioclient/include/media/AudioAttributes.h b/media/libaudioclient/include/media/VolumeGroupAttributes.h
similarity index 72%
rename from media/libaudioclient/include/media/AudioAttributes.h
rename to media/libaudioclient/include/media/VolumeGroupAttributes.h
index 24bd179..46b3612 100644
--- a/media/libaudioclient/include/media/AudioAttributes.h
+++ b/media/libaudioclient/include/media/VolumeGroupAttributes.h
@@ -26,15 +26,22 @@
 
 namespace android {
 
-class AudioAttributes : public Parcelable
+class VolumeGroupAttributes : public Parcelable
 {
 public:
-    AudioAttributes() = default;
-    AudioAttributes(const audio_attributes_t &attributes) : mAttributes(attributes) {} // NOLINT
-    AudioAttributes(volume_group_t groupId,
+    VolumeGroupAttributes() = default;
+    VolumeGroupAttributes(const audio_attributes_t &attributes)
+        : mAttributes(attributes) {} // NOLINT
+    VolumeGroupAttributes(volume_group_t groupId,
                     audio_stream_type_t stream,
                     const audio_attributes_t &attributes) :
-         mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {}
+         mAttributes(attributes), mStreamType(stream), mGroupId(groupId) {
+        // TODO: align native & JAVA source initializer.
+        // As far as this class concerns attributes for volume group, it applies only to playback.
+        mAttributes.source = AUDIO_SOURCE_INVALID;
+    }
+
+    int matchesScore(const audio_attributes_t &attributes) const;
 
     audio_attributes_t getAttributes() const { return mAttributes; }
 
@@ -61,8 +68,8 @@
 
 // AIDL conversion routines.
 ConversionResult<media::AudioAttributesEx>
-legacy2aidl_AudioAttributes_AudioAttributesEx(const AudioAttributes& legacy);
-ConversionResult<AudioAttributes>
-aidl2legacy_AudioAttributesEx_AudioAttributes(const media::AudioAttributesEx& aidl);
+legacy2aidl_VolumeGroupAttributes_AudioAttributesEx(const VolumeGroupAttributes& legacy);
+ConversionResult<VolumeGroupAttributes>
+aidl2legacy_AudioAttributesEx_VolumeGroupAttributes(const media::AudioAttributesEx& aidl);
 
 } // namespace android
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 91ef7b3..a7bb02a 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 ef8500b..97b37da 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,32 +119,33 @@
 TEST_F(SerializationTest, AudioProductStrategyBinderization) {
     for (int j = 0; j < 512; j++) {
         const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)};
-        std::vector<AudioAttributes> audioattributesvector;
+        SCOPED_TRACE(name);
+        std::vector<VolumeGroupAttributes> volumeGroupAttrVector;
         for (auto i = 0; i < 16; i++) {
             audio_attributes_t attributes;
             fillAudioAttributes(attributes);
-            AudioAttributes audioattributes{static_cast<volume_group_t>(rand()),
-                                            kStreamtypes[rand() % kStreamtypes.size()], attributes};
-            audioattributesvector.push_back(audioattributes);
+            VolumeGroupAttributes volumeGroupAttr{static_cast<volume_group_t>(rand()),
+                                                  kStreamtypes[rand() % kStreamtypes.size()],
+                                                  attributes};
+            volumeGroupAttrVector.push_back(volumeGroupAttr);
         }
         product_strategy_t psId = static_cast<product_strategy_t>(rand());
-        AudioProductStrategy aps{name, audioattributesvector, psId};
+        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;
-        auto avec = apsCopy.getAudioAttributes();
-        EXPECT_EQ(avec.size(), audioattributesvector.size()) << name;
-        for (int i = 0; i < audioattributesvector.size(); i++) {
-            EXPECT_EQ(avec[i].getGroupId(), audioattributesvector[i].getGroupId()) << name;
-            EXPECT_EQ(avec[i].getStreamType(), audioattributesvector[i].getStreamType()) << name;
-            EXPECT_TRUE(avec[i].getAttributes() == audioattributesvector[i].getAttributes())
-                    << 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());
+        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());
         }
     }
 }
@@ -293,17 +294,17 @@
     audio_stream_type_t stream = mAudioStream;
     audio_attributes_t attributes;
     fillAudioAttributes(attributes);
-    AudioAttributes audioattributes{groupId, stream, attributes};
+    VolumeGroupAttributes volumeGroupAttr{groupId, stream, attributes};
 
     Parcel p;
-    EXPECT_EQ(NO_ERROR, audioattributes.writeToParcel(&p)) << msg;
+    EXPECT_EQ(NO_ERROR, volumeGroupAttr.writeToParcel(&p)) << msg;
 
-    AudioAttributes audioattributesCopy;
+    VolumeGroupAttributes volumeGroupAttrCopy;
     p.setDataPosition(0);
-    EXPECT_EQ(NO_ERROR, audioattributesCopy.readFromParcel(&p)) << msg;
-    EXPECT_EQ(audioattributesCopy.getGroupId(), audioattributes.getGroupId()) << msg;
-    EXPECT_EQ(audioattributesCopy.getStreamType(), audioattributes.getStreamType()) << msg;
-    EXPECT_TRUE(audioattributesCopy.getAttributes() == attributes) << msg;
+    EXPECT_EQ(NO_ERROR, volumeGroupAttrCopy.readFromParcel(&p)) << msg;
+    EXPECT_EQ(volumeGroupAttrCopy.getGroupId(), volumeGroupAttr.getGroupId()) << msg;
+    EXPECT_EQ(volumeGroupAttrCopy.getStreamType(), volumeGroupAttr.getStreamType()) << msg;
+    EXPECT_TRUE(volumeGroupAttrCopy.getAttributes() == attributes) << msg;
 }
 
 // audioStream
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
index d43b669..f31bd95 100644
--- a/media/libaudioclient/tests/audiosystem_tests.cpp
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -347,7 +347,7 @@
 
 bool isPublicStrategy(const AudioProductStrategy& strategy) {
     bool result = true;
-    for (auto& attribute : strategy.getAudioAttributes()) {
+    for (auto& attribute : strategy.getVolumeGroupAttributes()) {
         if (attribute.getAttributes() == AUDIO_ATTRIBUTES_INITIALIZER &&
             (uint32_t(attribute.getStreamType()) >= AUDIO_STREAM_PUBLIC_CNT)) {
             result = false;
@@ -386,7 +386,7 @@
     for (const auto& strategy : strategies) {
         if (!isPublicStrategy(strategy)) continue;
 
-        for (const auto& att : strategy.getAudioAttributes()) {
+        for (const auto& att : strategy.getVolumeGroupAttributes()) {
             if (strategy.attributesMatches(att.getAttributes(), attributes)) {
                 hasStrategyForMedia = true;
                 mediaStrategy = strategy;
diff --git a/media/libaudiohal/TEST_MAPPING b/media/libaudiohal/TEST_MAPPING
index 3de5a9f..78a9dbc 100644
--- a/media/libaudiohal/TEST_MAPPING
+++ b/media/libaudiohal/TEST_MAPPING
@@ -7,6 +7,9 @@
           "include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic.*"
         }
       ]
+    },
+    {
+      "name": "CoreAudioHalAidlTest"
     }
   ]
 }
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index 30a4bf9..fc04cb3 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -240,19 +240,47 @@
     ]
 }
 
-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_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",
@@ -274,32 +302,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 db6b6cf..0fadd9c 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -18,8 +18,15 @@
 
 #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>
 #include <utils/String16.h>
 #include <utils/Vector.h>
 
@@ -51,4 +58,38 @@
     const std::string mClassName;
 };
 
+// 'action' must accept a value of type 'T' and return 'status_t'.
+// The function returns 'true' if the parameter was found, and the action has succeeded.
+// The function returns 'false' if the parameter was not found.
+// Any errors get propagated, if there are errors it means the parameter was found.
+template<typename T, typename F>
+error::Result<bool> filterOutAndProcessParameter(
+        AudioParameter& parameters, const String8& key, const F& action) {
+    if (parameters.containsKey(key)) {
+        T value;
+        status_t status = parameters.get(key, value);
+        if (status == OK) {
+            parameters.remove(key);
+            status = action(value);
+            if (status == OK) return true;
+        }
+        return base::unexpected(status);
+    }
+    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 e452a35..e6e7c6a 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -35,6 +35,7 @@
 #include "StreamHalAidl.h"
 
 using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::Boolean;
 using aidl::android::media::audio::common::AudioChannelLayout;
 using aidl::android::media::audio::common::AudioConfig;
 using aidl::android::media::audio::common::AudioDevice;
@@ -61,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;
@@ -68,10 +70,14 @@
 using aidl::android::hardware::audio::common::RecordTrackMetadata;
 using aidl::android::hardware::audio::core::AudioPatch;
 using aidl::android::hardware::audio::core::AudioRoute;
+using aidl::android::hardware::audio::core::IBluetooth;
+using aidl::android::hardware::audio::core::IBluetoothA2dp;
+using aidl::android::hardware::audio::core::IBluetoothLe;
 using aidl::android::hardware::audio::core::IModule;
 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 {
 
@@ -107,14 +113,33 @@
     return cpp;
 }
 
+template<typename T>
+std::shared_ptr<T> retrieveSubInterface(const std::shared_ptr<IModule>& module,
+        ::ndk::ScopedAStatus (IModule::*getT)(std::shared_ptr<T>*)) {
+    if (module != nullptr) {
+        std::shared_ptr<T> instance;
+        if (auto status = (module.get()->*getT)(&instance); status.isOk()) {
+            return instance;
+        }
+    }
+    return nullptr;
+}
+
 }  // namespace
 
+DeviceHalAidl::DeviceHalAidl(const std::string& instance, const std::shared_ptr<IModule>& module,
+                             const std::shared_ptr<IHalAdapterVendorExtension>& vext)
+        : ConversionHelperAidl("DeviceHalAidl"),
+          mInstance(instance), mModule(module), mVendorExt(vext),
+          mTelephony(retrieveSubInterface<ITelephony>(module, &IModule::getTelephony)),
+          mBluetooth(retrieveSubInterface<IBluetooth>(module, &IModule::getBluetooth)),
+          mBluetoothA2dp(retrieveSubInterface<IBluetoothA2dp>(module, &IModule::getBluetoothA2dp)),
+          mBluetoothLe(retrieveSubInterface<IBluetoothLe>(module, &IModule::getBluetoothLe)) {
+}
+
 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) {
@@ -124,6 +149,22 @@
     return OK;
 }
 
+status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
+    TIME_CHECK();
+    if (modes == nullptr) {
+        return BAD_VALUE;
+    }
+    if (mModule == nullptr) return NO_INIT;
+    if (mTelephony == nullptr) return INVALID_OPERATION;
+    std::vector<AudioMode> aidlModes;
+    RETURN_STATUS_IF_ERROR(
+            statusTFromBinderStatus(mTelephony->getSupportedAudioModes(&aidlModes)));
+    *modes = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::convertContainer<std::vector<media::audio::common::AudioMode>>(
+                    aidlModes, ndk2cpp_AudioMode));
+    return OK;
+}
+
 status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
     // Obsolete.
     return INVALID_OPERATION;
@@ -175,17 +216,14 @@
 status_t DeviceHalAidl::setVoiceVolume(float volume) {
     TIME_CHECK();
     if (!mModule) return NO_INIT;
-    std::shared_ptr<ITelephony> telephony;
-    if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
-            status.isOk() && telephony != nullptr) {
-        ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
-        RETURN_STATUS_IF_ERROR(
-                statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
-        ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
-                "%s: the resulting voice volume %f is not the same as requested %f",
-                __func__, outConfig.voiceVolume.value().value, volume);
-    }
-    return INVALID_OPERATION;
+    if (mTelephony == nullptr) return INVALID_OPERATION;
+    ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
+    RETURN_STATUS_IF_ERROR(
+            statusTFromBinderStatus(mTelephony->setTelecomConfig(inConfig, &outConfig)));
+    ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
+            "%s: the resulting voice volume %f is not the same as requested %f",
+            __func__, outConfig.voiceVolume.value().value, volume);
+    return OK;
 }
 
 status_t DeviceHalAidl::setMasterVolume(float volume) {
@@ -204,10 +242,8 @@
     TIME_CHECK();
     if (!mModule) return NO_INIT;
     AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
-    std::shared_ptr<ITelephony> telephony;
-    if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
-            status.isOk() && telephony != nullptr) {
-        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
+    if (mTelephony != nullptr) {
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
     }
     return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
 }
@@ -236,19 +272,41 @@
     return statusTFromBinderStatus(mModule->getMasterMute(state));
 }
 
-status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
-    TIME_CHECK();
+status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
     if (!mModule) return NO_INIT;
-    ALOGE("%s not implemented yet", __func__);
-    return OK;
+    AudioParameter parameters(kvPairs);
+    ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
+
+    if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
+        ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
+    }
+    if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
+        ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
+    }
+    if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
+        ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
+    }
+    if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
+        ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
+    }
+    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();
-    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 {
@@ -518,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();
     {
@@ -579,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;
@@ -1040,6 +1098,219 @@
     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) {
+                        if (trueOrFalse == AudioParameter::valueTrue) {
+                            a2dpEnabled = false;  // 'suspended' == true
+                            return OK;
+                        } else if (trueOrFalse == AudioParameter::valueFalse) {
+                            a2dpEnabled = true;  // 'suspended' == false
+                            return OK;
+                        }
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                AudioParameter::keyBtA2dpSuspended, trueOrFalse.c_str());
+                        return BAD_VALUE;
+                    }));
+    (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;
+}
+
+status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
+    TIME_CHECK();
+    IBluetooth::HfpConfig hfpConfig;
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyBtHfpEnable),
+                    [&hfpConfig](const String8& trueOrFalse) {
+                        if (trueOrFalse == AudioParameter::valueTrue) {
+                            hfpConfig.isEnabled = Boolean{ .value = true };
+                            return OK;
+                        } else if (trueOrFalse == AudioParameter::valueFalse) {
+                            hfpConfig.isEnabled = Boolean{ .value = false };
+                            return OK;
+                        }
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                AudioParameter::keyBtHfpEnable, trueOrFalse.c_str());
+                        return BAD_VALUE;
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                    parameters, String8(AudioParameter::keyBtHfpSamplingRate),
+                    [&hfpConfig](int sampleRate) {
+                        return sampleRate > 0 ?
+                                hfpConfig.sampleRate = Int{ .value = sampleRate }, OK : BAD_VALUE;
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                    parameters, String8(AudioParameter::keyBtHfpVolume),
+                    [&hfpConfig](int volume0to15) {
+                        if (volume0to15 >= 0 && volume0to15 <= 15) {
+                            hfpConfig.volume = Float{ .value = volume0to15 / 15.0f };
+                            return OK;
+                        }
+                        return BAD_VALUE;
+                    }));
+    if (mBluetooth != nullptr && hfpConfig != IBluetooth::HfpConfig{}) {
+        IBluetooth::HfpConfig newHfpConfig;
+        return statusTFromBinderStatus(mBluetooth->setHfpConfig(hfpConfig, &newHfpConfig));
+    }
+    return OK;
+}
+
+status_t DeviceHalAidl::filterAndUpdateBtLeParameters(AudioParameter &parameters) {
+    TIME_CHECK();
+    std::optional<bool> leEnabled;
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyBtLeSuspended),
+                    [&leEnabled](const String8& trueOrFalse) {
+                        if (trueOrFalse == AudioParameter::valueTrue) {
+                            leEnabled = false;  // 'suspended' == true
+                            return OK;
+                        } else if (trueOrFalse == AudioParameter::valueFalse) {
+                            leEnabled = true;  // 'suspended' == false
+                            return OK;
+                        }
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
+                        return BAD_VALUE;
+                    }));
+    if (mBluetoothLe != nullptr && leEnabled.has_value()) {
+        return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
+    }
+    return OK;
+}
+
+status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
+    TIME_CHECK();
+    IBluetooth::ScoConfig scoConfig;
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyBtSco),
+                    [&scoConfig](const String8& onOrOff) {
+                        if (onOrOff == AudioParameter::valueOn) {
+                            scoConfig.isEnabled = Boolean{ .value = true };
+                            return OK;
+                        } else if (onOrOff == AudioParameter::valueOff) {
+                            scoConfig.isEnabled = Boolean{ .value = false };
+                            return OK;
+                        }
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                AudioParameter::keyBtSco, onOrOff.c_str());
+                        return BAD_VALUE;
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyBtScoHeadsetName),
+                    [&scoConfig](const String8& name) {
+                        scoConfig.debugName = name;
+                        return OK;
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyBtNrec),
+                    [&scoConfig](const String8& onOrOff) {
+                        if (onOrOff == AudioParameter::valueOn) {
+                            scoConfig.isNrecEnabled = Boolean{ .value = true };
+                            return OK;
+                        } else if (onOrOff == AudioParameter::valueOff) {
+                            scoConfig.isNrecEnabled = Boolean{ .value = false };
+                            return OK;
+                        }
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                AudioParameter::keyBtNrec, onOrOff.c_str());
+                        return BAD_VALUE;
+                    }));
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
+                    parameters, String8(AudioParameter::keyBtScoWb),
+                    [&scoConfig](const String8& onOrOff) {
+                        if (onOrOff == AudioParameter::valueOn) {
+                            scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO_WB;
+                            return OK;
+                        } else if (onOrOff == AudioParameter::valueOff) {
+                            scoConfig.mode = IBluetooth::ScoConfig::Mode::SCO;
+                            return OK;
+                        }
+                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                                AudioParameter::keyBtScoWb, onOrOff.c_str());
+                        return BAD_VALUE;
+                    }));
+    if (mBluetooth != nullptr && scoConfig != IBluetooth::ScoConfig{}) {
+        IBluetooth::ScoConfig newScoConfig;
+        return statusTFromBinderStatus(mBluetooth->setScoConfig(scoConfig, &newScoConfig));
+    }
+    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 ea3e125..45768a3 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 <android-base/thread_annotations.h>
 #include <media/audiohal/DeviceHalInterface.h>
@@ -72,6 +73,8 @@
 
     status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
 
+    status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) override;
+
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
     status_t getSupportedDevices(uint32_t *devices) override;
 
@@ -197,8 +200,8 @@
     // Must not be constructed directly by clients.
     DeviceHalAidl(
             const std::string& instance,
-            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
-            : ConversionHelperAidl("DeviceHalAidl"), mInstance(instance), mModule(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;
 
@@ -209,6 +212,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,
@@ -282,6 +291,11 @@
 
     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;
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe> mBluetoothLe;
     Ports mPorts;
     int32_t mDefaultInputPortId = -1;
     int32_t mDefaultOutputPortId = -1;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index ad9e182..cd83171 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -88,6 +88,11 @@
     return INVALID_OPERATION;
 }
 
+status_t DeviceHalHidl::getSupportedModes(
+        std::vector<media::audio::common::AudioMode> *modes __unused) {
+    return INVALID_OPERATION;
+}
+
 status_t DeviceHalHidl::getSupportedDevices(uint32_t*) {
     // Obsolete.
     return INVALID_OPERATION;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 6b6c197..17acd2f 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -33,6 +33,8 @@
 
     status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) override;
 
+    status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) override;
+
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
     status_t getSupportedDevices(uint32_t *devices) override;
 
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/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index 52fed91..4c58fe9 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -72,14 +72,13 @@
 
 EffectConversionHelperAidl::EffectConversionHelperAidl(
         std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
-        int32_t sessionId, int32_t ioId, const Descriptor& desc)
+        int32_t sessionId, int32_t ioId, const Descriptor& desc, bool isProxy)
     : mSessionId(sessionId),
       mIoId(ioId),
       mDesc(desc),
       mEffect(std::move(effect)),
       mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC),
-      mIsProxyEffect(mDesc.common.id.proxy.has_value() &&
-                     mDesc.common.id.proxy.value() == mDesc.common.id.uuid) {
+      mIsProxyEffect(isProxy) {
     mCommon.session = sessionId;
     mCommon.ioHandle = ioId;
     mCommon.input = mCommon.output = kDefaultAudioConfig;
@@ -319,17 +318,25 @@
             mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
     return *static_cast<int32_t*>(pReplyData) = OK;
 }
+
 status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
-                                                     uint32_t* replySize __unused,
-                                                     void* pReplyData __unused) {
+                                                     uint32_t* replySize, void* pReplyData) {
     if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData) {
         ALOGE("%s parameter invalid %u %p", __func__, cmdSize, pCmdData);
         return BAD_VALUE;
     }
-    Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24),
-                                      .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)};
+
+    constexpr uint32_t unityGain = 1 << 24;
+    Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / unityGain,
+                                      .right = (float)(*(uint32_t*)pCmdData + 1) / unityGain};
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+
+    // write unity gain back if volume was successfully set
+    if (replySize && *replySize == 2 * sizeof(uint32_t) && pReplyData) {
+        constexpr uint32_t vol_ret[2] = {unityGain, unityGain};
+        memcpy(pReplyData, vol_ret, sizeof(vol_ret));
+    }
     return OK;
 }
 
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 0c682ff..e2cf87f 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -54,7 +54,7 @@
     EffectConversionHelperAidl(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxy);
 
     status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
                                 void* pReplyData);
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index faf5f45..a5f2c61 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -89,64 +89,64 @@
     ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
     if (typeUuid ==
         ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
-        mConversion =
-                std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId,
+                                                                           desc, mIsProxyEffect);
     } else if (typeUuid == ::aidl::android::hardware::audio::effect::
                                    getEffectTypeUuidAutomaticGainControlV1()) {
         mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
-                                                                            desc);
+                                                                            desc, mIsProxyEffect);
     } else if (typeUuid == ::aidl::android::hardware::audio::effect::
                                    getEffectTypeUuidAutomaticGainControlV2()) {
         mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
-                                                                            desc);
+                                                                            desc, mIsProxyEffect);
     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
-        mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(effect, sessionId,
-                                                                                 ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
-        mConversion = std::make_unique<android::effect::AidlConversionDownmix>(effect, sessionId,
-                                                                               ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionDownmix>(
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
-        mConversion =
-                std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId,
+                                                                          desc, mIsProxyEffect);
     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
-        mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(effect, sessionId,
-                                                                                 ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
-        mConversion =
-                std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId,
+                                                                          desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
         mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
         mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
         mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
         mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
         mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
         mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else if (typeUuid ==
                ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
-        mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(effect, sessionId,
-                                                                                  ioId, desc);
+        mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     } else {
         // For unknown UUID, use vendor extension implementation
         mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
-                effect, sessionId, ioId, desc);
+                effect, sessionId, ioId, desc, mIsProxyEffect);
     }
     return OK;
 }
diff --git a/media/libaudiohal/impl/EffectProxy.cpp b/media/libaudiohal/impl/EffectProxy.cpp
index b61532d..3bb045b 100644
--- a/media/libaudiohal/impl/EffectProxy.cpp
+++ b/media/libaudiohal/impl/EffectProxy.cpp
@@ -20,6 +20,7 @@
 //#define LOG_NDEBUG 0
 
 #include <fmq/AidlMessageQueue.h>
+#include <system/audio_aidl_utils.h>
 #include <utils/Log.h>
 
 #include "EffectProxy.h"
@@ -32,6 +33,7 @@
 using ::aidl::android::hardware::audio::effect::Parameter;
 using ::aidl::android::hardware::audio::effect::State;
 using ::aidl::android::media::audio::common::AudioUuid;
+using ::android::audio::utils::toString;
 
 namespace android {
 namespace effect {
@@ -54,7 +56,7 @@
 
 // sub effect must have same proxy UUID as EffectProxy, and the type UUID must match.
 ndk::ScopedAStatus EffectProxy::addSubEffect(const Descriptor& sub) {
-    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
     if (0 != mSubEffects.count(sub.common.id) || !sub.common.id.proxy.has_value() ||
         sub.common.id.proxy.value() != mIdentity.uuid) {
         ALOGE("%s sub effect already exist or mismatch %s", __func__, sub.toString().c_str());
@@ -92,15 +94,15 @@
 }
 
 ndk::ScopedAStatus EffectProxy::create() {
-    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
     ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
 
     for (auto& sub : mSubEffects) {
         auto& effectHandle = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
-        ALOGI("%s sub-effect %s", __func__, sub.first.uuid.toString().c_str());
+        ALOGI("%s sub-effect %s", __func__, toString(sub.first.uuid).c_str());
         status = mFactory->createEffect(sub.first.uuid, &effectHandle);
         if (!status.isOk() || !effectHandle) {
-            ALOGE("%s sub-effect failed %s", __func__, sub.first.uuid.toString().c_str());
+            ALOGE("%s sub-effect failed %s", __func__, toString(sub.first.uuid).c_str());
             break;
         }
     }
@@ -113,7 +115,7 @@
 }
 
 ndk::ScopedAStatus EffectProxy::destroy() {
-    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
     return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
         ndk::ScopedAStatus status = mFactory->destroyEffect(effect);
         if (status.isOk()) {
@@ -131,7 +133,7 @@
     const auto& itor = std::find_if(mSubEffects.begin(), mSubEffects.end(), [&](const auto& sub) {
         const auto& desc = std::get<SubEffectTupleIndex::DESCRIPTOR>(sub.second);
         ALOGI("%s: isOffload %d sub-effect: %s, flags %s", __func__, offload->isOffload,
-              desc.common.id.uuid.toString().c_str(), desc.common.flags.toString().c_str());
+              toString(desc.common.id.uuid).c_str(), desc.common.flags.toString().c_str());
         return offload->isOffload ==
                (desc.common.flags.hwAcceleratorMode == Flags::HardwareAccelerator::TUNNEL);
     });
@@ -143,7 +145,7 @@
 
     mActiveSub = itor->first;
     ALOGI("%s: active %soffload sub-effect: %s, flags %s", __func__,
-          offload->isOffload ? "" : "non-", mActiveSub.uuid.toString().c_str(),
+          offload->isOffload ? "" : "non-", toString(mActiveSub.uuid).c_str(),
           std::get<SubEffectTupleIndex::DESCRIPTOR>(itor->second).common.flags.toString().c_str());
     return ndk::ScopedAStatus::ok();
 }
@@ -152,14 +154,14 @@
 ndk::ScopedAStatus EffectProxy::open(const Parameter::Common& common,
                                      const std::optional<Parameter::Specific>& specific,
                                      IEffect::OpenEffectReturn* ret __unused) {
-    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
     ndk::ScopedAStatus status = ndk::ScopedAStatus::fromExceptionCodeWithMessage(
             EX_ILLEGAL_ARGUMENT, "nullEffectHandle");
     for (auto& sub : mSubEffects) {
         auto& effect = std::get<SubEffectTupleIndex::HANDLE>(sub.second);
         auto& openRet = std::get<SubEffectTupleIndex::RETURN>(sub.second);
         if (!effect || !(status = effect->open(common, specific, &openRet)).isOk()) {
-            ALOGE("%s: failed to open UUID %s", __func__, sub.first.uuid.toString().c_str());
+            ALOGE("%s: failed to open UUID %s", __func__, toString(sub.first.uuid).c_str());
             break;
         }
     }
@@ -173,7 +175,7 @@
 }
 
 ndk::ScopedAStatus EffectProxy::close() {
-    ALOGV("%s: %s", __func__, mIdentity.type.toString().c_str());
+    ALOGV("%s: %s", __func__, toString(mIdentity.type).c_str());
     return runWithAllSubEffects([&](std::shared_ptr<IEffect>& effect) {
         return effect->close();
     });
@@ -203,7 +205,7 @@
 
 // Handle with active sub-effect first, only send to other sub-effects when success
 ndk::ScopedAStatus EffectProxy::command(CommandId id) {
-    ALOGV("%s: %s, command %s", __func__, mIdentity.type.toString().c_str(),
+    ALOGV("%s: %s, command %s", __func__, toString(mIdentity.type).c_str(),
           android::internal::ToString(id).c_str());
     return runWithActiveSubEffectThenOthers(
             [&](const std::shared_ptr<IEffect>& effect) -> ndk::ScopedAStatus {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 0dcb8ee..f278ca0 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -28,6 +28,7 @@
 #include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionEffect.h>
 #include <system/audio.h>
+#include <system/audio_aidl_utils.h>
 #include <utils/Log.h>
 
 #include "EffectBufferHalAidl.h"
@@ -40,7 +41,10 @@
 using ::aidl::android::hardware::audio::effect::Descriptor;
 using ::aidl::android::hardware::audio::effect::IFactory;
 using ::aidl::android::hardware::audio::effect::Processing;
+using ::aidl::android::media::audio::common::AudioSource;
+using ::aidl::android::media::audio::common::AudioStreamType;
 using ::aidl::android::media::audio::common::AudioUuid;
+using ::android::audio::utils::toString;
 using ::android::base::unexpected;
 using ::android::detail::AudioHalVersionInfo;
 
@@ -96,7 +100,13 @@
           return list;
       }()),
       mEffectCount(mNonProxyDescList.size() + mProxyDescList.size()),
-      mEffectProcessings(nullptr /* TODO: add AIDL implementation */) {
+      mAidlProcessings([this]() -> std::vector<Processing> {
+          std::vector<Processing> processings;
+          if (!mFactory || !mFactory->queryProcessing(std::nullopt, &processings).isOk()) {
+              ALOGE("%s queryProcessing failed", __func__);
+          }
+          return processings;
+      }()) {
     ALOG_ASSERT(mFactory != nullptr, "Provided IEffectsFactory service is NULL");
     ALOGI("%s with %zu nonProxyEffects and %zu proxyEffects", __func__, mNonProxyDescList.size(),
           mProxyDescList.size());
@@ -180,7 +190,7 @@
                 statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
     }
     if (aidlEffect == nullptr) {
-        ALOGE("%s failed to create effect with UUID: %s", __func__, aidlUuid.toString().c_str());
+        ALOGE("%s failed to create effect with UUID: %s", __func__, toString(aidlUuid).c_str());
         return NAME_NOT_FOUND;
     }
     Descriptor desc;
@@ -236,10 +246,10 @@
     auto matchIt = std::find_if(list.begin(), list.end(),
                                 [&](const auto& desc) { return desc.common.id.uuid == uuid; });
     if (matchIt == list.end()) {
-        ALOGE("%s UUID not found in HAL and proxy list %s", __func__, uuid.toString().c_str());
+        ALOGE("%s UUID not found in HAL and proxy list %s", __func__, toString(uuid).c_str());
         return BAD_VALUE;
     }
-    ALOGI("%s UUID impl found %s", __func__, uuid.toString().c_str());
+    ALOGI("%s UUID impl found %s", __func__, toString(uuid).c_str());
 
     *pDescriptor = VALUE_OR_RETURN_STATUS(
             ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
@@ -258,10 +268,10 @@
     std::copy_if(mProxyDescList.begin(), mProxyDescList.end(), std::back_inserter(result),
                  [&](auto& desc) { return desc.common.id.type == type; });
     if (result.empty()) {
-        ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, type.toString().c_str());
+        ALOGW("%s UUID type not found in HAL and proxy list %s", __func__, toString(type).c_str());
         return BAD_VALUE;
     }
-    ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), type.toString().c_str());
+    ALOGI("%s UUID type found %zu \n %s", __func__, result.size(), toString(type).c_str());
 
     *descriptors = VALUE_OR_RETURN_STATUS(
             aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
@@ -274,15 +284,79 @@
 }
 
 std::shared_ptr<const effectsConfig::Processings> EffectsFactoryHalAidl::getProcessings() const {
-    return mEffectProcessings;
+
+    auto getConfigEffectWithDescriptor =
+            [](const auto& desc) -> std::shared_ptr<const effectsConfig::Effect> {
+        effectsConfig::Effect effect = {.name = desc.common.name, .isProxy = false};
+        if (const auto uuid =
+                    ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(desc.common.id.uuid);
+            uuid.ok()) {
+            static_cast<effectsConfig::EffectImpl>(effect).uuid = uuid.value();
+            return std::make_shared<const effectsConfig::Effect>(effect);
+        } else {
+            return nullptr;
+        }
+    };
+
+    auto getConfigProcessingWithAidlProcessing =
+            [&](const auto& aidlProcess, std::vector<effectsConfig::InputStream>& preprocess,
+                std::vector<effectsConfig::OutputStream>& postprocess) {
+                if (aidlProcess.type.getTag() == Processing::Type::streamType) {
+                    AudioStreamType aidlType =
+                            aidlProcess.type.template get<Processing::Type::streamType>();
+                    const auto type =
+                            ::aidl::android::aidl2legacy_AudioStreamType_audio_stream_type_t(
+                                    aidlType);
+                    if (!type.ok()) {
+                        return;
+                    }
+
+                    std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+                    std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+                                   std::back_inserter(effects), getConfigEffectWithDescriptor);
+                    effectsConfig::OutputStream stream = {.type = type.value(),
+                                                          .effects = std::move(effects)};
+                    postprocess.emplace_back(stream);
+                } else if (aidlProcess.type.getTag() == Processing::Type::source) {
+                    AudioSource aidlType =
+                            aidlProcess.type.template get<Processing::Type::source>();
+                    const auto type =
+                            ::aidl::android::aidl2legacy_AudioSource_audio_source_t(aidlType);
+                    if (!type.ok()) {
+                        return;
+                    }
+
+                    std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+                    std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+                                   std::back_inserter(effects), getConfigEffectWithDescriptor);
+                    effectsConfig::InputStream stream = {.type = type.value(),
+                                                         .effects = std::move(effects)};
+                    preprocess.emplace_back(stream);
+                }
+            };
+
+    static std::shared_ptr<const effectsConfig::Processings> processings(
+            [&]() -> std::shared_ptr<const effectsConfig::Processings> {
+                std::vector<effectsConfig::InputStream> preprocess;
+                std::vector<effectsConfig::OutputStream> postprocess;
+                for (const auto& processing : mAidlProcessings) {
+                    getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess);
+                }
+
+                if (0 == preprocess.size() && 0 == postprocess.size()) {
+                    return nullptr;
+                }
+
+                return std::make_shared<const effectsConfig::Processings>(
+                        effectsConfig::Processings({.preprocess = std::move(preprocess),
+                                                    .postprocess = std::move(postprocess)}));
+            }());
+
+    return processings;
 }
 
+// Return 0 for AIDL, as the AIDL interface is not aware of the configuration file.
 ::android::error::Result<size_t> EffectsFactoryHalAidl::getSkippedElements() const {
-    if (!mEffectProcessings) {
-        return ::android::base::unexpected(BAD_VALUE);
-    }
-
-    // Only return 0 for AIDL, because the AIDL interface doesn't aware of configuration file
     return 0;
 }
 
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
index 70a7012..39beea2 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -21,6 +21,7 @@
 #include <mutex>
 
 #include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/hardware/audio/effect/Processing.h>
 #include <android-base/thread_annotations.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
 #include <system/thread_defs.h>
@@ -82,7 +83,7 @@
     // total number of effects including proxy effects
     const size_t mEffectCount;
     // Query result of pre and post processing from effect factory
-    const std::shared_ptr<const effectsConfig::Processings> mEffectProcessings;
+    const std::vector<Processing> mAidlProcessings;
 
     std::mutex mLock;
     uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0;  // Align with HIDL (0 is INVALID_ID)
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index eccdfe8..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;
@@ -122,34 +125,9 @@
     return OK;
 }
 
-namespace {
-
-// 'action' must accept a value of type 'T' and return 'status_t'.
-// The function returns 'true' if the parameter was found, and the action has succeeded.
-// The function returns 'false' if the parameter was not found.
-// Any errors get propagated, if there are errors it means the parameter was found.
-template<typename T, typename F>
-error::Result<bool> filterOutAndProcessParameter(
-        AudioParameter& parameters, const String8& key, const F& action) {
-    if (parameters.containsKey(key)) {
-        T value;
-        status_t status = parameters.get(key, value);
-        if (status == OK) {
-            parameters.remove(key);
-            status = action(value);
-            if (status == OK) return true;
-        }
-        return base::unexpected(status);
-    }
-    return false;
-}
-
-}  // namespace
-
 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());
 
@@ -158,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) {
@@ -557,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);
@@ -579,10 +559,10 @@
     if (!mStream) return NO_INIT;
 
     AudioParameter parameters(kvPairs);
-    ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
+    ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
 
     if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
-        ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
+        ALOGW("%s: filtering or updating offload metadata failed: %d", __func__, status);
     }
 
     return StreamHalAidl::setParameters(parameters.toString());
@@ -885,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/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2b0af49..82062cc 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -979,9 +979,10 @@
 }
 
 status_t StreamOutHalHidl::exit() {
-    // Signal exiting to remote_submix HAL.
+    // Signal exiting to HALs that use intermediate pipes to close them.
     AudioParameter param;
     param.addInt(String8(AudioParameter::keyExiting), 1);
+    param.add(String8(AudioParameter::keyClosing), String8(AudioParameter::valueTrue));
     return setParameters(param.toString());
 }
 
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
index 3ee419a..61dd36a 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
@@ -26,8 +26,9 @@
   public:
     AidlConversionAec(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
                       int32_t sessionId, int32_t ioId,
-                      const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+                      const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                      bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionAec() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
index b0509fd..364b473 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
@@ -26,8 +26,9 @@
   public:
     AidlConversionAgc1(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
                        int32_t sessionId, int32_t ioId,
-                       const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+                       const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                       bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionAgc1() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
index 8f7eac7..df9a9ec 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
@@ -26,8 +26,9 @@
   public:
     AidlConversionAgc2(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
                        int32_t sessionId, int32_t ioId,
-                       const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+                       const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                       bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionAgc2() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
index 9664aa1..424b837 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
@@ -27,8 +27,8 @@
     AidlConversionBassBoost(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionBassBoost() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
index 8b28ca3..f963f66 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
@@ -26,8 +26,9 @@
   public:
     AidlConversionDownmix(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
                           int32_t sessionId, int32_t ioId,
-                          const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+                          const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                          bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionDownmix() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
index c5d5a54..62714c3 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
@@ -26,8 +26,9 @@
   public:
     AidlConversionDp(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
                      int32_t sessionId, int32_t ioId,
-                     const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+                     const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                     bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionDp() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
index 8b92374..95042eb 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
@@ -27,8 +27,8 @@
     AidlConversionEnvReverb(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionEnvReverb() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
index 45b98a1..fc867c7 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -161,6 +161,9 @@
             return param.writeToValue(&bands);
         }
         case EQ_PARAM_LEVEL_RANGE: {
+            if (mDesc.capability.range.getTag() != Range::equalizer) {
+                return OK;
+            }
             const auto& ranges = mDesc.capability.range.get<Range::equalizer>();
             for (const auto& r : ranges) {
                 if (r.min.getTag() == Equalizer::bandLevels &&
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
index f94556c..53566e2 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -25,9 +25,10 @@
 class AidlConversionEq : public EffectConversionHelperAidl {
   public:
     AidlConversionEq(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
-                      int32_t sessionId, int32_t ioId,
-                      const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+                     int32_t sessionId, int32_t ioId,
+                     const ::aidl::android::hardware::audio::effect::Descriptor& desc,
+                     bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionEq() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
index 03114a5..9890bfb 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
@@ -27,8 +27,8 @@
     AidlConversionHapticGenerator(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionHapticGenerator() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
index c0402f9..2ce14a6 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
@@ -27,8 +27,8 @@
     AidlConversionLoudnessEnhancer(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionLoudnessEnhancer() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
index f51e13a..fac121d 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
@@ -27,8 +27,8 @@
     AidlConversionNoiseSuppression(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionNoiseSuppression() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
index 397d6e6..b975d72 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
@@ -27,8 +27,8 @@
     AidlConversionPresetReverb(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionPresetReverb() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
index c44567c..7c60b14 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
@@ -27,8 +27,8 @@
     AidlConversionSpatializer(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionSpatializer() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
index fd22e5c..16bfeba 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
@@ -27,8 +27,8 @@
     AidlConversionVendorExtension(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionVendorExtension() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
index 91c0fcd..359d884 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
@@ -27,8 +27,8 @@
     AidlConversionVirtualizer(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionVirtualizer() {}
 
   private:
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
index e380bc6..bc9320f 100644
--- a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -27,8 +27,8 @@
     AidlConversionVisualizer(
             std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
             int32_t sessionId, int32_t ioId,
-            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
-        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc, bool isProxyEffect)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc, isProxyEffect) {}
     ~AidlConversionVisualizer() {}
 
   private:
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index b0f8656..0103680 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -19,6 +19,7 @@
 
 #include <android/media/audio/common/AudioMMapPolicyInfo.h>
 #include <android/media/audio/common/AudioMMapPolicyType.h>
+#include <android/media/audio/common/AudioMode.h>
 #include <android/media/audio/common/AudioPort.h>
 #include <android/media/AudioRoute.h>
 #include <error/Result.h>
@@ -40,6 +41,8 @@
 
     virtual status_t getAudioRoutes(std::vector<media::AudioRoute> *routes) = 0;
 
+    virtual status_t getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) = 0;
+
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
     virtual status_t getSupportedDevices(uint32_t *devices) = 0;
 
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/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
index c076ccc..63f895f 100644
--- a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -15,6 +15,7 @@
  */
 
 //#define LOG_NDEBUG 0
+#include <algorithm>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
@@ -92,6 +93,47 @@
     }
 }
 
+TEST(libAudioHalTest, getProcessings) {
+    auto factory = EffectsFactoryHalInterface::create();
+    ASSERT_NE(nullptr, factory);
+
+    const auto &processings = factory->getProcessings();
+    if (processings) {
+        EXPECT_NE(0UL, processings->preprocess.size() + processings->postprocess.size() +
+                               processings->deviceprocess.size());
+
+        auto processingChecker = [](const auto& processings) {
+            if (processings.size() != 0) {
+                // any process need at least 1 effect inside
+                std::for_each(processings.begin(), processings.end(), [](const auto& process) {
+                    EXPECT_NE(0ul, process.effects.size());
+                    // any effect should have a valid name string, and not proxy
+                    for (const auto& effect : process.effects) {
+                        SCOPED_TRACE("Effect: {" +
+                                     (effect == nullptr
+                                              ? "NULL}"
+                                              : ("{name: " + effect->name + ", isproxy: " +
+                                                 (effect->isProxy ? "true" : "false") + ", sw: " +
+                                                 (effect->libSw ? "non-null" : "null") + ", hw: " +
+                                                 (effect->libHw ? "non-null" : "null") + "}")));
+                        EXPECT_NE(nullptr, effect);
+                        EXPECT_NE("", effect->name);
+                        EXPECT_EQ(false, effect->isProxy);
+                        EXPECT_EQ(nullptr, effect->libSw);
+                        EXPECT_EQ(nullptr, effect->libHw);
+                    }
+                });
+            }
+        };
+
+        processingChecker(processings->preprocess);
+        processingChecker(processings->postprocess);
+        processingChecker(processings->deviceprocess);
+    } else {
+        GTEST_SKIP() << "no processing found, skipping the test";
+    }
+}
+
 TEST(libAudioHalTest, getHalVersion) {
     auto factory = EffectsFactoryHalInterface::create();
     ASSERT_NE(nullptr, factory);
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
index 309765a..6160d7d 100644
--- a/media/libaudioprocessing/Android.bp
+++ b/media/libaudioprocessing/Android.bp
@@ -72,6 +72,10 @@
     ],
 
     whole_static_libs: ["libaudioprocessing_base"],
+
+    export_shared_lib_headers: [
+        "libvibrator",
+    ],
 }
 
 cc_library_static {
diff --git a/media/libaudioprocessing/AudioMixerBase.cpp b/media/libaudioprocessing/AudioMixerBase.cpp
index f30eb54..3c34caa 100644
--- a/media/libaudioprocessing/AudioMixerBase.cpp
+++ b/media/libaudioprocessing/AudioMixerBase.cpp
@@ -453,9 +453,9 @@
                         &track->mVolume[param - VOLUME0],
                         &track->mPrevVolume[param - VOLUME0],
                         &track->mVolumeInc[param - VOLUME0])) {
-                    ALOGV("setParameter(%s, VOLUME%d: %04x)",
-                            target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
-                                    track->volume[param - VOLUME0]);
+                    ALOGV("setParameter(%s, VOLUME%d: %f)",
+                          target == VOLUME ? "VOLUME" : "RAMP_VOLUME", param - VOLUME0,
+                          track->mVolume[param - VOLUME0]);
                     invalidate();
                 }
             } else {
@@ -630,7 +630,7 @@
 
         if (t->volumeInc[0]|t->volumeInc[1]) {
             volumeRamp = true;
-        } else if (!t->doesResample() && t->volumeRL == 0) {
+        } else if (!t->doesResample() && t->isVolumeMuted()) {
             n |= NEEDS_MUTE;
         }
         t->needs = n;
@@ -730,7 +730,7 @@
 
         for (const int name : mEnabled) {
             const std::shared_ptr<TrackBase> &t = mTracks[name];
-            if (!t->doesResample() && t->volumeRL == 0) {
+            if (!t->doesResample() && t->isVolumeMuted()) {
                 t->needs |= NEEDS_MUTE;
                 t->hook = &TrackBase::track__nop;
             } else {
diff --git a/media/libaudioprocessing/include/media/AudioMixerBase.h b/media/libaudioprocessing/include/media/AudioMixerBase.h
index 3419816..0d82255 100644
--- a/media/libaudioprocessing/include/media/AudioMixerBase.h
+++ b/media/libaudioprocessing/include/media/AudioMixerBase.h
@@ -290,6 +290,16 @@
         audio_channel_mask_t mMixerChannelMask;
         uint32_t             mMixerChannelCount;
 
+        // consider volume muted only if all channel volume (floating point) is 0.f
+        inline bool isVolumeMuted() const {
+            for (const auto volume : mVolume) {
+                if (volume != 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
       protected:
 
         // hooks
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index a9730e5..09a060d 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -49,26 +49,27 @@
     std::string name;
     std::string path;
 };
-using Libraries = std::vector<Library>;
+using Libraries = std::vector<std::shared_ptr<const Library>>;
 
 struct EffectImpl {
-    Library* library; //< Only valid as long as the associated library vector is unmodified
+    //< Only valid as long as the associated library vector is unmodified
+    std::shared_ptr<const Library> library;
     effect_uuid_t uuid;
 };
 
 struct Effect : public EffectImpl {
     std::string name;
     bool isProxy;
-    EffectImpl libSw; //< Only valid if isProxy
-    EffectImpl libHw; //< Only valid if isProxy
+    std::shared_ptr<EffectImpl> libSw; //< Only valid if isProxy
+    std::shared_ptr<EffectImpl> libHw; //< Only valid if isProxy
 };
 
-using Effects = std::vector<Effect>;
+using Effects = std::vector<std::shared_ptr<const Effect>>;
 
 template <class Type>
 struct Stream {
     Type type;
-    std::vector<std::reference_wrapper<Effect>> effects;
+    Effects effects;
 };
 using OutputStream = Stream<audio_stream_type_t>;
 using InputStream = Stream<audio_source_t>;
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 3096659..2ff057e 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -19,6 +19,7 @@
 #include <algorithm>
 #include <cstdint>
 #include <functional>
+#include <memory>
 #include <string>
 #include <unistd.h>
 
@@ -149,7 +150,10 @@
         ALOGE("library must have a name and a path: %s", dump(xmlLibrary));
         return false;
     }
-    libraries->push_back({name, path});
+
+    // need this temp variable because `struct Library` doesn't have a constructor
+    Library lib({.name = name, .path = path});
+    libraries->push_back(std::make_shared<const Library>(lib));
     return true;
 }
 
@@ -157,10 +161,10 @@
  * @return nullptr if not found, the element address if found.
  */
 template <class T>
-T* findByName(const char* name, std::vector<T>& collection) {
+T findByName(const char* name, std::vector<T>& collection) {
     auto it = find_if(begin(collection), end(collection),
-                         [name] (auto& item) { return item.name == name; });
-    return it != end(collection) ? &*it : nullptr;
+                      [name](auto& item) { return item && item->name == name; });
+    return it != end(collection) ? *it : nullptr;
 }
 
 /** Parse an effect from an xml element describing it.
@@ -187,7 +191,7 @@
         }
 
         // Convert library name to a pointer to the previously loaded library
-        auto* library = findByName(libraryName, libraries);
+        auto library = findByName(libraryName, libraries);
         if (library == nullptr) {
             ALOGE("Could not find library referenced in: %s", dump(xmlImpl));
             return false;
@@ -211,20 +215,25 @@
         effect.isProxy = true;
 
         // Function to parse libhw and libsw
-        auto parseProxy = [&xmlEffect, &parseImpl](const char* tag, EffectImpl& proxyLib) {
+        auto parseProxy = [&xmlEffect, &parseImpl](const char* tag,
+                                                   const std::shared_ptr<EffectImpl>& proxyLib) {
             auto* xmlProxyLib = xmlEffect.FirstChildElement(tag);
             if (xmlProxyLib == nullptr) {
                 ALOGE("effectProxy must contain a <%s>: %s", tag, dump(xmlEffect));
                 return false;
             }
-            return parseImpl(*xmlProxyLib, proxyLib);
+            return parseImpl(*xmlProxyLib, *proxyLib);
         };
+        effect.libSw = std::make_shared<EffectImpl>();
+        effect.libHw = std::make_shared<EffectImpl>();
         if (!parseProxy("libhw", effect.libHw) || !parseProxy("libsw", effect.libSw)) {
+            effect.libSw.reset();
+            effect.libHw.reset();
             return false;
         }
     }
 
-    effects->push_back(std::move(effect));
+    effects->push_back(std::make_shared<const Effect>(effect));
     return true;
 }
 
@@ -250,12 +259,12 @@
             ALOGE("<stream|device>/apply must have reference an effect: %s", dump(xmlApply));
             return false;
         }
-        auto* effect = findByName(effectName, effects);
+        auto effect = findByName(effectName, effects);
         if (effect == nullptr) {
             ALOGE("Could not find effect referenced in: %s", dump(xmlApply));
             return false;
         }
-        stream.effects.emplace_back(*effect);
+        stream.effects.emplace_back(effect);
     }
     streams->push_back(std::move(stream));
     return true;
diff --git a/media/libeffects/factory/EffectsConfigLoader.c b/media/libeffects/factory/EffectsConfigLoader.c
index e23530e..a1de7b3 100644
--- a/media/libeffects/factory/EffectsConfigLoader.c
+++ b/media/libeffects/factory/EffectsConfigLoader.c
@@ -137,7 +137,7 @@
                  kLibraryPathRoot[i],
                  lib_name);
         if (F_OK == access(path, 0)) {
-            strcpy(lib_path_out, path);
+            strlcpy(lib_path_out, path, PATH_MAX);
             ALOGW_IF(strncmp(lib_path_out, lib_path_in, PATH_MAX) != 0,
                 "checkLibraryPath() corrected library path %s to %s", lib_path_in, lib_path_out);
             return 0;
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
index 30a9007..9bff136 100644
--- a/media/libeffects/factory/EffectsXmlConfigLoader.cpp
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -64,7 +64,7 @@
 
     std::string absolutePath;
     if (!resolveLibrary(relativePath, &absolutePath)) {
-        ALOGE("Could not find library in effect directories: %s", relativePath);
+        ALOGE("%s Could not find library in effect directories: %s", __func__, relativePath);
         libEntry->path = strdup(relativePath);
         return false;
     }
@@ -75,20 +75,20 @@
     std::unique_ptr<void, decltype(dlclose)*> libHandle(dlopen(path, RTLD_NOW),
                                                        dlclose);
     if (libHandle == nullptr) {
-        ALOGE("Could not dlopen library %s: %s", path, dlerror());
+        ALOGE("%s Could not dlopen library %s: %s", __func__, path, dlerror());
         return false;
     }
 
     auto* description = static_cast<audio_effect_library_t*>(
           dlsym(libHandle.get(), AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR));
     if (description == nullptr) {
-        ALOGE("Invalid effect library, failed not find symbol '%s' in %s: %s",
+        ALOGE("%s Invalid effect library, failed not find symbol '%s' in %s: %s", __func__,
               AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR, path, dlerror());
         return false;
     }
 
     if (description->tag != AUDIO_EFFECT_LIBRARY_TAG) {
-        ALOGE("Bad tag %#08x in description structure, expected %#08x for library %s",
+        ALOGE("%s Bad tag %#08x in description structure, expected %#08x for library %s", __func__,
               description->tag, AUDIO_EFFECT_LIBRARY_TAG, path);
         return false;
     }
@@ -96,8 +96,8 @@
     uint32_t majorVersion = EFFECT_API_VERSION_MAJOR(description->version);
     uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_LIBRARY_API_VERSION_CURRENT);
     if (majorVersion != expectedMajorVersion) {
-        ALOGE("Unsupported major version %#08x, expected %#08x for library %s",
-              majorVersion, expectedMajorVersion, path);
+        ALOGE("%s Unsupported major version %#08x, expected %#08x for library %s",
+              __func__, majorVersion, expectedMajorVersion, path);
         return false;
     }
 
@@ -155,14 +155,13 @@
 {
     size_t nbSkippedElement = 0;
     for (auto& library : libs) {
-
         // Construct a lib entry
         auto libEntry = makeUniqueC<lib_entry_t>();
-        libEntry->name = strdup(library.name.c_str());
+        libEntry->name = strdup(library->name.c_str());
         libEntry->effects = nullptr;
         pthread_mutex_init(&libEntry->lock, nullptr);
 
-        if (!loadLibrary(library.path.c_str(), libEntry.get())) {
+        if (!loadLibrary(library->path.c_str(), libEntry.get())) {
             // Register library load failure
             listPush(std::move(libEntry), libFailedList);
             ++nbSkippedElement;
@@ -209,24 +208,24 @@
     UniqueCPtr<effect_descriptor_t> effectDesc;
 };
 
-LoadEffectResult loadEffect(const EffectImpl& effect, const std::string& name,
-                            list_elem_t* libList) {
+LoadEffectResult loadEffect(const std::shared_ptr<const EffectImpl>& effect,
+                            const std::string& name, list_elem_t* libList) {
     LoadEffectResult result;
 
     // Find the effect library
-    result.lib = findLibrary(effect.library->name.c_str(), libList);
+    result.lib = findLibrary(effect->library->name.c_str(), libList);
     if (result.lib == nullptr) {
-        ALOGE("Could not find library %s to load effect %s",
-              effect.library->name.c_str(), name.c_str());
+        ALOGE("%s Could not find library %s to load effect %s",
+              __func__, effect->library->name.c_str(), name.c_str());
         return result;
     }
 
     result.effectDesc = makeUniqueC<effect_descriptor_t>();
 
     // Get the effect descriptor
-    if (result.lib->desc->get_descriptor(&effect.uuid, result.effectDesc.get()) != 0) {
+    if (result.lib->desc->get_descriptor(&effect->uuid, result.effectDesc.get()) != 0) {
         ALOGE("Error querying effect %s on lib %s",
-              uuidToString(effect.uuid), result.lib->name);
+              uuidToString(effect->uuid), result.lib->name);
         result.effectDesc.reset();
         return result;
     }
@@ -241,14 +240,15 @@
     // Check effect is supported
     uint32_t expectedMajorVersion = EFFECT_API_VERSION_MAJOR(EFFECT_CONTROL_API_VERSION);
     if (EFFECT_API_VERSION_MAJOR(result.effectDesc->apiVersion) != expectedMajorVersion) {
-        ALOGE("Bad API version %#08x for effect %s in lib %s, expected major %#08x",
+        ALOGE("%s Bad API version %#08x for effect %s in lib %s, expected major %#08x", __func__,
               result.effectDesc->apiVersion, name.c_str(), result.lib->name, expectedMajorVersion);
         return result;
     }
 
     lib_entry_t *_;
-    if (findEffect(nullptr, &effect.uuid, &_, nullptr) == 0) {
-        ALOGE("Effect %s uuid %s already exist", uuidToString(effect.uuid), name.c_str());
+    if (findEffect(nullptr, &effect->uuid, &_, nullptr) == 0) {
+        ALOGE("%s Effect %s uuid %s already exist", __func__, uuidToString(effect->uuid),
+              name.c_str());
         return result;
     }
 
@@ -261,8 +261,11 @@
     size_t nbSkippedElement = 0;
 
     for (auto& effect : effects) {
+        if (!effect) {
+            continue;
+        }
 
-        auto effectLoadResult = loadEffect(effect, effect.name, libList);
+        auto effectLoadResult = loadEffect(effect, effect->name, libList);
         if (!effectLoadResult.success) {
             if (effectLoadResult.effectDesc != nullptr) {
                 listPush(std::move(effectLoadResult.effectDesc), skippedEffects);
@@ -271,9 +274,9 @@
             continue;
         }
 
-        if (effect.isProxy) {
-            auto swEffectLoadResult = loadEffect(effect.libSw, effect.name + " libsw", libList);
-            auto hwEffectLoadResult = loadEffect(effect.libHw, effect.name + " libhw", libList);
+        if (effect->isProxy) {
+            auto swEffectLoadResult = loadEffect(effect->libSw, effect->name + " libsw", libList);
+            auto hwEffectLoadResult = loadEffect(effect->libHw, effect->name + " libhw", libList);
             if (!swEffectLoadResult.success || !hwEffectLoadResult.success) {
                 // Push the main effect in the skipped list even if only a subeffect is invalid
                 // as the main effect is not usable without its subeffects.
@@ -287,7 +290,7 @@
             // get_descriptor call, we replace it with the corresponding
             // sw effect descriptor, but keep the Proxy UUID
             *effectLoadResult.effectDesc = *swEffectLoadResult.effectDesc;
-            effectLoadResult.effectDesc->uuid = effect.uuid;
+            effectLoadResult.effectDesc->uuid = effect->uuid;
 
             effectLoadResult.effectDesc->flags |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
 
@@ -326,8 +329,8 @@
                                loadEffects(result.parsedConfig->effects, gLibraryList,
                                            &gSkippedEffects, &gSubEffectList);
 
-    ALOGE_IF(result.nbSkippedElement != 0, "%zu errors during loading of configuration: %s",
-             result.nbSkippedElement,
+    ALOGE_IF(result.nbSkippedElement != 0, "%s %zu errors during loading of configuration: %s",
+             __func__, result.nbSkippedElement,
              result.configPath.empty() ? "No config file found" : result.configPath.c_str());
 
     return result.nbSkippedElement;
diff --git a/media/libeffects/factory/test/DumpConfig.cpp b/media/libeffects/factory/test/DumpConfig.cpp
index 0a156b4..331826f 100644
--- a/media/libeffects/factory/test/DumpConfig.cpp
+++ b/media/libeffects/factory/test/DumpConfig.cpp
@@ -14,54 +14,49 @@
  * limitations under the License.
  */
 
+#include <getopt.h>
+
 #include <media/EffectsFactoryApi.h>
-#include <unistd.h>
 #include "EffectsXmlConfigLoader.h"
 #include "EffectsConfigLoader.h"
 
 int main(int argc, char* argv[]) {
-    const char* path = nullptr;
-    bool legacyFormat;
+    const char* const short_opts = "lx:h";
+    const option long_opts[] = {{"legacy", no_argument, nullptr, 'l'},
+                                {"xml", optional_argument, nullptr, 'x'},
+                                {"help", no_argument, nullptr, 'h'}};
 
-    if (argc == 2 && strcmp(argv[1], "--legacy") == 0) {
-        legacyFormat = true;
-        fprintf(stderr, "Dumping legacy effect config file\n");
-    } else if ((argc == 2 || argc == 3) && strcmp(argv[1], "--xml") == 0) {
-        legacyFormat = false;
-        if (argc == 3) {
-            fprintf(stderr, "Dumping XML effect config file: %s\n", path);
-        } else {
-            fprintf(stderr, "Dumping default XML effect config file.\n");
+    const auto opt = getopt_long(argc, argv, short_opts, long_opts, nullptr);
+    switch (opt) {
+        case 'l': { // -l or --legacy
+            printf("Dumping legacy effect config file\n");
+            if (EffectLoadEffectConfig() < 0) {
+                fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
+                return 1;
+            }
+            return EffectDumpEffects(STDOUT_FILENO);
         }
-    } else {
-        fprintf(stderr, "Invalid arguments.\n"
-                        "Usage: %s [--legacy|--xml [FILE]]\n", argv[0]);
-        return 1;
-    }
-
-    if (!legacyFormat) {
-        ssize_t ret = EffectLoadXmlEffectConfig(path);
-        if (ret < 0) {
-            fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
-            return 2;
+        case 'x': { // -x or --xml
+            printf("Dumping effect config file: %s\n", (optarg == NULL) ? "default" : optarg);
+            ssize_t ret = EffectLoadXmlEffectConfig(optarg);
+            if (ret < 0) {
+                fprintf(stderr, "loadXmlEffectConfig failed, see logcat for detail.\n");
+                return 1;
+            }
+            if (ret > 0) {
+                printf("Partially failed to load config. Skipped %zu elements.\n",
+                        (size_t)ret);
+            }
+            return EffectDumpEffects(STDOUT_FILENO);
         }
-        if (ret > 0) {
-            fprintf(stderr, "Partially failed to load config. Skipped %zu elements, "
-                    "see logcat for detail.\n", (size_t)ret);
+        case 'h': // -h or --help
+        default: {
+            printf("Usage: %s\n"
+                   "--legacy (or -l):        Legacy audio effect config file to load\n"
+                   "--xml (or -x) <FILE>:    Audio effect config file to load\n"
+                   "--help (or -h):          Show this help\n",
+                   argv[0]);
+            return 0;
         }
     }
-
-    if (legacyFormat) {
-        auto ret = EffectLoadEffectConfig();
-        if (ret < 0) {
-            fprintf(stderr, "loadEffectConfig failed, see logcat for detail.\n");
-            return 3;
-        }
-        fprintf(stderr, "legacy loadEffectConfig has probably succeed, see logcat to make sure.\n");
-    }
-
-    if (EffectDumpEffects(STDOUT_FILENO) != 0) {
-        fprintf(stderr, "Effect dump failed, see logcat for detail.\n");
-        return 4;
-    }
 }
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
index 4eea04f..bfc5059 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.cpp
@@ -166,9 +166,9 @@
              * Bypass mode or everything off, so copy the input to the output
              */
             if (pToProcess != pProcessed) {
-                Copy_Float(pToProcess,                          /* Source */
-                           pProcessed,                          /* Destination */
-                           (LVM_INT16)(NrChannels * NrFrames)); /* Copy all samples */
+                Copy_Float(pToProcess,   /* Source */
+                           pProcessed,   /* Destination */
+                           SampleCount); /* Copy all samples */
             }
 
             /*
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
index d026e2b..0db7a73 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -15,9 +15,11 @@
  */
 
 #include <cstddef>
+#include <cstdio>
 
 #define LOG_TAG "BundleContext"
 #include <android-base/logging.h>
+#include <audio_utils/power.h>
 #include <Utils.h>
 
 #include "BundleContext.h"
@@ -34,7 +36,7 @@
     std::lock_guard lg(mMutex);
     // init with pre-defined preset NORMAL
     for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
-        mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i];
+        mBandGainMdB[i] = lvm::kSoftPresets[0 /* normal */][i] * 100;
     }
 
     // allocate lvm instance
@@ -212,7 +214,7 @@
 
         if (eqEnabled) {
             for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
-                float bandFactor = mBandGaindB[i] / 15.0;
+                float bandFactor = mBandGainMdB[i] / 1500.0;
                 float bandCoefficient = lvm::kBandEnergyCoefficient[i];
                 float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
                 if (bandEnergy > 0) energyContribution += bandEnergy;
@@ -221,8 +223,8 @@
             // cross EQ coefficients
             float bandFactorSum = 0;
             for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
-                float bandFactor1 = mBandGaindB[i] / 15.0;
-                float bandFactor2 = mBandGaindB[i + 1] / 15.0;
+                float bandFactor1 = mBandGainMdB[i] / 1500.0;
+                float bandFactor2 = mBandGainMdB[i + 1] / 1500.0;
 
                 if (bandFactor1 > 0 && bandFactor2 > 0) {
                     float crossEnergy =
@@ -244,7 +246,7 @@
 
             if (eqEnabled) {
                 for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
-                    float bandFactor = mBandGaindB[i] / 15.0;
+                    float bandFactor = mBandGainMdB[i] / 1500.0;
                     float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
                     float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
                     if (bandEnergy > 0) energyBassBoost += bandEnergy;
@@ -397,15 +399,10 @@
     return db_fix;
 }
 
-// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude
-int16_t BundleContext::VolToDb(uint32_t vol) const {
-    int16_t dB;
-
-    dB = LVC_ToDB_s32Tos16(vol << 7);
-    dB = (dB + 8) >> 4;
-    dB = (dB < -96) ? -96 : dB;
-
-    return dB;
+/* static */
+float BundleContext::VolToDb(float vol) {
+    float dB = audio_utils_power_from_amplitude(vol);
+    return std::max(dB, -96.f);
 }
 
 RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
@@ -413,11 +410,12 @@
     LVM_ReturnStatus_en status = LVM_SUCCESS;
 
     // Convert volume to dB
-    int leftdB = VolToDb(volume.left);
-    int rightdB = VolToDb(volume.right);
-    int maxdB = std::max(leftdB, rightdB);
-    int pandB = rightdB - leftdB;
-    setVolumeLevel(maxdB * 100);
+    float leftdB = VolToDb(volume.left);
+    float rightdB = VolToDb(volume.right);
+
+    float maxdB = std::max(leftdB, rightdB);
+    float pandB = rightdB - leftdB;
+    setVolumeLevel(maxdB);
     LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
 
     {
@@ -441,8 +439,8 @@
     std::vector<Equalizer::BandLevel> bandLevels;
     bandLevels.reserve(lvm::MAX_NUM_BANDS);
     for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
-        bandLevels.emplace_back(
-                Equalizer::BandLevel{static_cast<int32_t>(i), lvm::kSoftPresets[presetIdx][i]});
+        bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i),
+                                                     lvm::kSoftPresets[presetIdx][i] * 100});
     }
 
     RetCode ret = updateControlParameter(bandLevels);
@@ -472,7 +470,8 @@
     std::vector<Equalizer::BandLevel> bandLevels;
     bandLevels.reserve(lvm::MAX_NUM_BANDS);
     for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
-        bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i), mBandGaindB[i]});
+        bandLevels.emplace_back(
+                Equalizer::BandLevel{static_cast<int32_t>(i), mBandGainMdB[i]});
     }
     return bandLevels;
 }
@@ -506,7 +505,7 @@
     RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
                     "indexOutOfRange");
 
-    std::array<int, lvm::MAX_NUM_BANDS> tempLevel;
+    std::array<int, lvm::MAX_NUM_BANDS> tempLevel(mBandGainMdB);
     for (const auto& it : bandLevels) {
         tempLevel[it.index] = it.levelMb;
     }
@@ -520,14 +519,16 @@
         for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
             params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
             params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
-            params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+            params.pEQNB_BandDefinition[i].Gain =
+                    tempLevel[i] > 0 ? (tempLevel[i] + 50) / 100 : (tempLevel[i] - 50) / 100;
         }
 
         RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
                         RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
     }
-    mBandGaindB = tempLevel;
-    LOG(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
+    mBandGainMdB = tempLevel;
+    LOG(DEBUG) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGainMdB)
+               << "mdB";
 
     return RetCode::SUCCESS;
 }
@@ -551,18 +552,18 @@
     return limitLevel();
 }
 
-RetCode BundleContext::setVolumeLevel(int level) {
+RetCode BundleContext::setVolumeLevel(float level) {
     if (mMuteEnabled) {
-        mLevelSaved = level / 100;
+        mLevelSaved = level;
     } else {
-        mVolume = level / 100;
+        mVolume = level;
     }
     LOG(INFO) << __func__ << " success with level " << level;
     return limitLevel();
 }
 
-int BundleContext::getVolumeLevel() const {
-    return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100);
+float BundleContext::getVolumeLevel() const {
+    return (mMuteEnabled ? mLevelSaved : mVolume);
 }
 
 RetCode BundleContext::setVolumeMute(bool mute) {
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 47d5e5a..62bb6e4 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -80,8 +80,8 @@
     RetCode setBassBoostStrength(int strength);
     int getBassBoostStrength() const { return mBassStrengthSaved; }
 
-    RetCode setVolumeLevel(int level);
-    int getVolumeLevel() const;
+    RetCode setVolumeLevel(float level);
+    float getVolumeLevel() const;
 
     RetCode setVolumeMute(bool mute);
     int getVolumeMute() const { return mMuteEnabled; }
@@ -135,20 +135,20 @@
     int mBassStrengthSaved = 0;
     // Equalizer
     int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
-    std::array<int, lvm::MAX_NUM_BANDS> mBandGaindB;
+    std::array<int, lvm::MAX_NUM_BANDS> mBandGainMdB; /* band gain in millibels */
     // Virtualizer
     int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
     bool mVirtualizerTempDisabled = false;
     ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
     // Volume
-    int mLevelSaved = 0; /* for when mute is set, level must be saved */
-    int mVolume = 0;
+    float mLevelSaved = 0; /* for when mute is set, level must be saved */
+    float mVolume = 0;
     bool mMuteEnabled = false; /* Must store as mute = -96dB level */
 
     void initControlParameter(LVM_ControlParams_t& params) const;
     void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
     RetCode limitLevel();
-    int16_t VolToDb(uint32_t vol) const;
+    static float VolToDb(float vol);
     LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
     RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
     bool isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel>& bandLevels) const;
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
index b3371a3..143329d 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -73,9 +73,9 @@
         MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
         MAKE_RANGE(Equalizer, bandLevels,
                    std::vector<Equalizer::BandLevel>{
-                           Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+                           Equalizer::BandLevel({.index = 0, .levelMb = -1500})},
                    std::vector<Equalizer::BandLevel>{
-                           Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 15})}),
+                           Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 1500})}),
         /* capability definition */
         MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency),
         MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets),
@@ -85,9 +85,7 @@
 static const std::string kEqualizerEffectName = "EqualizerBundle";
 static const Descriptor kEqualizerDesc = {
         .common = {.id = {.type = getEffectTypeUuidEqualizer(),
-                          .uuid = getEffectImplUuidEqualizerBundle(),
-                          .proxy = getEffectImplUuidEqualizerProxy()},
-
+                          .uuid = getEffectImplUuidEqualizerBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL},
@@ -102,8 +100,7 @@
 static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
 static const Descriptor kBassBoostDesc = {
         .common = {.id = {.type = getEffectTypeUuidBassBoost(),
-                          .uuid = getEffectImplUuidBassBoostBundle(),
-                          .proxy = getEffectImplUuidBassBoostProxy()},
+                          .uuid = getEffectImplUuidBassBoostBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::FIRST,
                              .volume = Flags::Volume::CTRL,
@@ -121,8 +118,7 @@
 
 static const Descriptor kVirtualizerDesc = {
         .common = {.id = {.type = getEffectTypeUuidVirtualizer(),
-                          .uuid = getEffectImplUuidVirtualizerBundle(),
-                          .proxy = getEffectImplUuidVirtualizerProxy()},
+                          .uuid = getEffectImplUuidVirtualizerBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::LAST,
                              .volume = Flags::Volume::CTRL,
@@ -139,8 +135,7 @@
 static const std::string kVolumeEffectName = "Volume";
 static const Descriptor kVolumeDesc = {
         .common = {.id = {.type = getEffectTypeUuidVolume(),
-                          .uuid = getEffectImplUuidVolumeBundle(),
-                          .proxy = std::nullopt},
+                          .uuid = getEffectImplUuidVolumeBundle()},
                    .flags = {.type = Flags::Type::INSERT,
                              .insert = Flags::Insert::LAST,
                              .volume = Flags::Volume::CTRL},
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index cd9fb60..eb7ab1a 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -355,7 +355,7 @@
     auto tag = id.get<Volume::Id::commonTag>();
     switch (tag) {
         case Volume::levelDb: {
-            volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+            volParam.set<Volume::levelDb>(static_cast<int>(mContext->getVolumeLevel()));
             break;
         }
         case Volume::mute: {
@@ -384,6 +384,7 @@
 
     if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) {
         auto angles = mContext->getSpeakerAngles(id.get<Virtualizer::Id::speakerAnglesPayload>());
+        RETURN_IF(angles.size() == 0, EX_ILLEGAL_ARGUMENT, "getSpeakerAnglesFailed");
         Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
         specific->set<Parameter::Specific::virtualizer>(param);
         return ndk::ScopedAStatus::ok();
diff --git a/media/libmedia/CharacterEncodingDetector.cpp b/media/libmedia/CharacterEncodingDetector.cpp
index 64ba977..e33cc0f 100644
--- a/media/libmedia/CharacterEncodingDetector.cpp
+++ b/media/libmedia/CharacterEncodingDetector.cpp
@@ -393,10 +393,6 @@
         while (true) {
             // demerit the current encoding for each "special" character found after conversion.
             // The amount of demerit is somewhat arbitrarily chosen.
-            int inchar;
-            if (source != sourceLimit) {
-                inchar = (source[0] << 8) + source[1];
-            }
             UChar32 c = ucnv_getNextUChar(conv, &source, sourceLimit, &status);
             if (!U_SUCCESS(status)) {
                 break;
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index c66861b..649f813 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -49,8 +49,9 @@
         "liblog",
     ],
     header_libs: [
-        "libmedia_helper_headers",
         "libaudio_system_headers",
+        "libhardware_headers",
+        "libmedia_helper_headers",
     ],
     export_header_lib_headers: [
         "libmedia_helper_headers",
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index e25f9b7..3832e90 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 
 #include <media/AudioParameter.h>
+#include <hardware/audio.h>
 #include <system/audio.h>
 
 namespace android {
@@ -32,9 +33,16 @@
 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;
+const char * const AudioParameter::keyBtScoHeadsetName = AUDIO_PARAMETER_KEY_BT_SCO_HEADSET_NAME;
 const char * const AudioParameter::keyBtNrec = AUDIO_PARAMETER_KEY_BT_NREC;
+const char * const AudioParameter::keyBtScoWb = AUDIO_PARAMETER_KEY_BT_SCO_WB;
+const char * const AudioParameter::keyBtHfpEnable = AUDIO_PARAMETER_KEY_HFP_ENABLE;
+const char * const AudioParameter::keyBtHfpSamplingRate = AUDIO_PARAMETER_KEY_HFP_SET_SAMPLING_RATE;
+const char * const AudioParameter::keyBtHfpVolume = AUDIO_PARAMETER_KEY_HFP_VOLUME;
 const char * const AudioParameter::keyHwAvSync = AUDIO_PARAMETER_HW_AV_SYNC;
 const char * const AudioParameter::keyPresentationId = AUDIO_PARAMETER_STREAM_PRESENTATION_ID;
 const char * const AudioParameter::keyProgramId = AUDIO_PARAMETER_STREAM_PROGRAM_ID;
@@ -52,9 +60,13 @@
         AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES;
 const char * const AudioParameter::valueOn = AUDIO_PARAMETER_VALUE_ON;
 const char * const AudioParameter::valueOff = AUDIO_PARAMETER_VALUE_OFF;
+const char * const AudioParameter::valueTrue = AUDIO_PARAMETER_VALUE_TRUE;
+const char * const AudioParameter::valueFalse = AUDIO_PARAMETER_VALUE_FALSE;
 const char * const AudioParameter::valueListSeparator = AUDIO_PARAMETER_VALUE_LIST_SEPARATOR;
+const char * const AudioParameter::keyBtA2dpSuspended = AUDIO_PARAMETER_KEY_BT_A2DP_SUSPENDED;
 const char * const AudioParameter::keyReconfigA2dp = AUDIO_PARAMETER_RECONFIG_A2DP;
 const char * const AudioParameter::keyReconfigA2dpSupported = AUDIO_PARAMETER_A2DP_RECONFIG_SUPPORTED;
+const char * const AudioParameter::keyBtLeSuspended = AUDIO_PARAMETER_KEY_BT_LE_SUSPENDED;
 // const char * const AudioParameter::keyDeviceSupportedEncapsulationModes =
 //        AUDIO_PARAMETER_DEVICE_SUP_ENCAPSULATION_MODES;
 // const char * const AudioParameter::keyDeviceSupportedEncapsulationMetadataTypes =
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 6c34a4f..3eee854 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,18 +49,29 @@
     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.
+    // keyClosing: "true" on AudioFlinger Thread preExit.  Used by A2DP HAL.
     // keyExiting: "1" on AudioFlinger Thread preExit.  Used by remote_submix and A2DP HAL.
     static const char * const keyClosing;
     static const char * const keyExiting;
 
+    //  keyBtSco: Whether BT SCO is 'on' or 'off'
+    //  keyBtScoHeadsetName: BT SCO headset name (for debugging)
     //  keyBtNrec: BT SCO Noise Reduction + Echo Cancellation parameters
+    //  keyBtScoWb: BT SCO NR wideband mode
+    //  keyHfp...: Parameters of the Hands-Free Profile
+    static const char * const keyBtSco;
+    static const char * const keyBtScoHeadsetName;
+    static const char * const keyBtNrec;
+    static const char * const keyBtScoWb;
+    static const char * const keyBtHfpEnable;
+    static const char * const keyBtHfpSamplingRate;
+    static const char * const keyBtHfpVolume;
+
     //  keyHwAvSync: get HW synchronization source identifier from a device
     //  keyMonoOutput: Enable mono audio playback
     //  keyStreamHwAvSync: set HW synchronization source identifier on a stream
-    static const char * const keyBtNrec;
     static const char * const keyHwAvSync;
     static const char * const keyMonoOutput;
     static const char * const keyStreamHwAvSync;
@@ -90,13 +102,19 @@
 
     static const char * const valueOn;
     static const char * const valueOff;
+    static const char * const valueTrue;
+    static const char * const valueFalse;
 
     static const char * const valueListSeparator;
 
+    // keyBtA2dpSuspended: 'true' or 'false'
     // keyReconfigA2dp: Ask HwModule to reconfigure A2DP offloaded codec
     // keyReconfigA2dpSupported: Query if HwModule supports A2DP offload codec config
+    // keyBtLeSuspended: 'true' or 'false'
+    static const char * const keyBtA2dpSuspended;
     static const char * const keyReconfigA2dp;
     static const char * const keyReconfigA2dpSupported;
+    static const char * const keyBtLeSuspended;
 
     // For querying device supported encapsulation capabilities. All returned values are integer,
     // which are bit fields composed from using encapsulation capability values as position bits.
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index fdcf246..e5f9789 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -388,7 +388,9 @@
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
                             ? asString_VP9Profile(pl.mProfile) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
-                            ? asString_AV1Profile(pl.mProfile) : "??";
+                            ? asString_AV1Profile(pl.mProfile) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)
+                            ? asString_DolbyVisionProfile(pl.mProfile) : "??";
                     const char *niceLevel =
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_MPEG2)
                             ? asString_MPEG2Level(pl.mLevel) :
@@ -405,7 +407,9 @@
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_VP9)
                             ? asString_VP9Level(pl.mLevel) :
                         mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_AV1)
-                            ? asString_AV1Level(pl.mLevel) : "??";
+                            ? asString_AV1Level(pl.mLevel) :
+                        mediaType.equalsIgnoreCase(MIMETYPE_VIDEO_DOLBY_VISION)
+                            ? asString_DolbyVisionLevel(pl.mLevel) : "??";
 
                     list.add(AStringPrintf("% 5u/% 5u (%s/%s)",
                             pl.mProfile, pl.mLevel, niceProfile, niceLevel));
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index ec79b99..6f8c102 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1254,10 +1254,6 @@
         case OUTPUT_FORMAT_MPEG_4:
         case OUTPUT_FORMAT_WEBM:
         {
-            bool isMPEG4 = true;
-            if (mOutputFormat == OUTPUT_FORMAT_WEBM) {
-                isMPEG4 = false;
-            }
             sp<MetaData> meta = new MetaData;
             setupMPEG4orWEBMMetaData(&meta);
             status = mWriter->start(meta.get());
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index d205990..f73c5a8 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -2217,6 +2217,11 @@
                 -ret, strerror(-ret));
             return ret;
         }
+        if (mVideoDecoder != NULL) {
+            sp<AMessage> params = new AMessage();
+            params->setInt32("android._video-scaling", mode);
+            mVideoDecoder->setParameters(params);
+        }
     }
     return OK;
 }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 8da09c4..f4143da 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -459,6 +459,14 @@
         codecParams->setFloat("operating-rate", decodeFrameRate * mPlaybackSpeed);
         mCodec->setParameters(codecParams);
     }
+
+    int32_t videoScalingMode;
+    if (params->findInt32("android._video-scaling", &videoScalingMode)
+            && mCodec != NULL) {
+        sp<AMessage> codecParams = new AMessage();
+        codecParams->setInt32("android._video-scaling", videoScalingMode);
+        mCodec->setParameters(codecParams);
+    }
 }
 
 void NuPlayer::Decoder::onSetRenderer(const sp<Renderer> &renderer) {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ccbe995..47cc357 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -293,6 +293,8 @@
         }
     }
 
+    void setSurfaceParameters(const sp<AMessage> &msg);
+
 private:
     // Handles an OMX message. Returns true iff message was handled.
     bool onOMXMessage(const sp<AMessage> &msg);
@@ -6502,6 +6504,59 @@
     postFillThisBuffer(eligible);
 }
 
+void ACodec::BaseState::setSurfaceParameters(const sp<AMessage> &msg) {
+    sp<AMessage> params;
+    CHECK(msg->findMessage("params", &params));
+
+    status_t err = mCodec->setSurfaceParameters(params);
+    if (err != OK) {
+        ALOGE("[%s] Unable to set input surface parameters (err %d)",
+                mCodec->mComponentName.c_str(),
+                err);
+        return;
+    }
+
+    int64_t timeOffsetUs;
+    if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
+        params->removeEntryAt(params->findEntryByName(PARAMETER_KEY_OFFSET_TIME));
+
+        if (params->countEntries() == 0) {
+            msg->removeEntryAt(msg->findEntryByName("params"));
+            return;
+        }
+    }
+
+    int64_t skipFramesBeforeUs;
+    if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
+        params->removeEntryAt(params->findEntryByName("skip-frames-before"));
+
+        if (params->countEntries() == 0) {
+            msg->removeEntryAt(msg->findEntryByName("params"));
+            return;
+        }
+    }
+
+    int32_t dropInputFrames;
+    if (params->findInt32(PARAMETER_KEY_SUSPEND, &dropInputFrames)) {
+        params->removeEntryAt(params->findEntryByName(PARAMETER_KEY_SUSPEND));
+
+        if (params->countEntries() == 0) {
+            msg->removeEntryAt(msg->findEntryByName("params"));
+            return;
+        }
+    }
+
+    int64_t stopTimeUs;
+    if (params->findInt64("stop-time-us", &stopTimeUs)) {
+        params->removeEntryAt(params->findEntryByName("stop-time-us"));
+
+        if (params->countEntries() == 0) {
+            msg->removeEntryAt(msg->findEntryByName("params"));
+            return;
+        }
+    }
+}
+
 bool ACodec::BaseState::onOMXFillBufferDone(
         IOMX::buffer_id bufferID,
         size_t rangeOffset, size_t rangeLength,
@@ -7368,6 +7423,13 @@
 bool ACodec::LoadedToIdleState::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatSetParameters:
+        {
+            BaseState::setSurfaceParameters(msg);
+            if (msg->countEntries() > 0) {
+                mCodec->deferMessage(msg);
+            }
+            return true;
+        }
         case kWhatShutdown:
         {
             mCodec->deferMessage(msg);
@@ -7444,6 +7506,13 @@
 bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatSetParameters:
+        {
+            BaseState::setSurfaceParameters(msg);
+            if (msg->countEntries() > 0) {
+                mCodec->deferMessage(msg);
+            }
+            return true;
+        }
         case kWhatShutdown:
         {
             mCodec->deferMessage(msg);
@@ -7723,27 +7792,7 @@
     return handled;
 }
 
-status_t ACodec::setParameters(const sp<AMessage> &params) {
-    int32_t videoBitrate;
-    if (params->findInt32("video-bitrate", &videoBitrate)) {
-        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
-        InitOMXParams(&configParams);
-        configParams.nPortIndex = kPortIndexOutput;
-        configParams.nEncodeBitrate = videoBitrate;
-
-        status_t err = mOMXNode->setConfig(
-                OMX_IndexConfigVideoBitrate,
-                &configParams,
-                sizeof(configParams));
-
-        if (err != OK) {
-            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
-                   videoBitrate, err);
-
-            return err;
-        }
-    }
-
+status_t ACodec::setSurfaceParameters(const sp<AMessage> &params) {
     int64_t timeOffsetUs;
     if (params->findInt64(PARAMETER_KEY_OFFSET_TIME, &timeOffsetUs)) {
         if (mGraphicBufferSource == NULL) {
@@ -7831,9 +7880,41 @@
         mInputFormat->setInt64("android._stop-time-offset-us", stopTimeOffsetUs);
     }
 
+    return OK;
+}
+
+status_t ACodec::setParameters(const sp<AMessage> &params) {
+    status_t err;
+
+    int32_t videoBitrate;
+    if (params->findInt32("video-bitrate", &videoBitrate)) {
+        OMX_VIDEO_CONFIG_BITRATETYPE configParams;
+        InitOMXParams(&configParams);
+        configParams.nPortIndex = kPortIndexOutput;
+        configParams.nEncodeBitrate = videoBitrate;
+
+        err = mOMXNode->setConfig(
+                OMX_IndexConfigVideoBitrate,
+                &configParams,
+                sizeof(configParams));
+
+        if (err != OK) {
+            ALOGE("setConfig(OMX_IndexConfigVideoBitrate, %d) failed w/ err %d",
+                   videoBitrate, err);
+
+            return err;
+        }
+    }
+
+    err = setSurfaceParameters(params);
+    if (err != OK) {
+        ALOGE("Failed to set input surface parameters (err %d)", err);
+        return err;
+    }
+
     int32_t tmp;
     if (params->findInt32("request-sync", &tmp)) {
-        status_t err = requestIDRFrame();
+        err = requestIDRFrame();
 
         if (err != OK) {
             ALOGE("Requesting a sync frame failed w/ err %d", err);
@@ -7848,7 +7929,7 @@
         rateFloat = (float) rateInt; // 16MHz (FLINTMAX) is OK for upper bound.
     }
     if (rateFloat > 0) {
-        status_t err = setOperatingRate(rateFloat, mIsVideo);
+        err = setOperatingRate(rateFloat, mIsVideo);
         if (err != OK) {
             ALOGI("Failed to set parameter 'operating-rate' (err %d)", err);
         }
@@ -7857,7 +7938,7 @@
     int32_t intraRefreshPeriod = 0;
     if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
             && intraRefreshPeriod > 0) {
-        status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
+        err = setIntraRefreshPeriod(intraRefreshPeriod, false);
         if (err != OK) {
             ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
                     mComponentName.c_str());
@@ -7867,7 +7948,7 @@
 
     int32_t lowLatency = 0;
     if (params->findInt32("low-latency", &lowLatency)) {
-        status_t err = setLowLatency(lowLatency);
+        err = setLowLatency(lowLatency);
         if (err != OK) {
             return err;
         }
@@ -7875,7 +7956,7 @@
 
     int32_t latency = 0;
     if (params->findInt32("latency", &latency) && latency > 0) {
-        status_t err = setLatency(latency);
+        err = setLatency(latency);
         if (err != OK) {
             ALOGI("[%s] failed setLatency. Failure is fine since this key is optional",
                     mComponentName.c_str());
@@ -7887,7 +7968,7 @@
     if (params->findInt32("audio-presentation-presentation-id", &presentationId)) {
         int32_t programId = -1;
         params->findInt32("audio-presentation-program-id", &programId);
-        status_t err = setAudioPresentation(presentationId, programId);
+        err = setAudioPresentation(presentationId, programId);
         if (err != OK) {
             ALOGI("[%s] failed setAudioPresentation. Failure is fine since this key is optional",
                     mComponentName.c_str());
@@ -7960,7 +8041,7 @@
     {
         int32_t tunnelPeek = 0;
         if (params->findInt32(TUNNEL_PEEK_KEY, &tunnelPeek)) {
-            status_t err = setTunnelPeek(tunnelPeek);
+            err = setTunnelPeek(tunnelPeek);
             if (err != OK) {
                 return err;
             }
@@ -7969,7 +8050,7 @@
     {
         int32_t tunnelPeekSetLegacy = 0;
         if (params->findInt32(TUNNEL_PEEK_SET_LEGACY_KEY, &tunnelPeekSetLegacy)) {
-            status_t err = setTunnelPeekLegacy(tunnelPeekSetLegacy);
+            err = setTunnelPeekLegacy(tunnelPeekSetLegacy);
             if (err != OK) {
                 return err;
             }
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 386b790..89ebe7b 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -31,7 +31,6 @@
 #include <utils/Log.h>
 
 #include <functional>
-#include <fcntl.h>
 
 #include <media/stagefright/MediaSource.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -556,6 +555,10 @@
     mResetStatus = OK;
     mPreAllocFirstTime = true;
     mPrevAllTracksTotalMetaDataSizeEstimate = 0;
+    mIsFirstChunk = false;
+    mDone = false;
+    mThread = 0;
+    mDriftTimeUs = 0;
 
     // Following variables only need to be set for the first recording session.
     // And they will stay the same for all the recording sessions.
diff --git a/media/libstagefright/VideoFrameSchedulerBase.cpp b/media/libstagefright/VideoFrameSchedulerBase.cpp
index 0d1517b..965014c 100644
--- a/media/libstagefright/VideoFrameSchedulerBase.cpp
+++ b/media/libstagefright/VideoFrameSchedulerBase.cpp
@@ -451,7 +451,7 @@
                 return origRenderTime;
             }
 
-            ATRACE_INT("FRAME_VSYNCS", vsyncsForLastFrame);
+            ATRACE_INT64("FRAME_VSYNCS", vsyncsForLastFrame);
         }
         mLastVsyncTime = nextVsyncTime;
     }
@@ -460,7 +460,7 @@
     renderTime -= (renderTime - mVsyncTime) % mVsyncPeriod;
     renderTime += mVsyncPeriod / 2;
     ALOGV("adjusting render: %lld => %lld", (long long)origRenderTime, (long long)renderTime);
-    ATRACE_INT("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
+    ATRACE_INT64("FRAME_FLIP_IN(ms)", (renderTime - now) / 1000000);
     return renderTime;
 }
 
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index b29c3b6..8b1ea03 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -331,8 +331,8 @@
             <Limit name="alignment" value="2x2" />
             <Limit name="block-size" value="8x8" />
             <Limit name="block-count" range="1-4096" /> <!-- max 512x512 -->
-            <Limit name="blocks-per-second" range="1-122880" />
-            <Limit name="frame-rate" range="1-120" />
+            <Limit name="blocks-per-second" range="1-259200" />
+            <Limit name="frame-rate" range="1-300" />
             <Limit name="bitrate" range="1-10000000" />
             <Limit name="complexity" range="0-10"  default="0" />
             <Limit name="quality" range="0-100"  default="80" />
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 38a4c1e..76b9633 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -601,6 +601,7 @@
             status_t internalError = UNKNOWN_ERROR);
 
     status_t requestIDRFrame();
+    status_t setSurfaceParameters(const sp<AMessage> &params);
     status_t setParameters(const sp<AMessage> &params);
 
     // set vendor extension parameters specified in params that are supported by the codec
diff --git a/media/libstagefright/tests/HEVC/AndroidTest.xml b/media/libstagefright/tests/HEVC/AndroidTest.xml
index ff850a2..00bb3e5 100644
--- a/media/libstagefright/tests/HEVC/AndroidTest.xml
+++ b/media/libstagefright/tests/HEVC/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="false" />
         <option name="push" value="HEVCUtilsUnitTest->/data/local/tmp/HEVCUtilsUnitTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest.zip?unzip=true"
-            value="/data/local/tmp/HEVCUtilsUnitTest/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="HEVCUtilsUnitTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="HEVCUtilsUnitTest-1.0" />
+        <option name="dynamic-config-module" value="HEVCUtilsUnitTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="HEVCUtilsUnitTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/HEVCUtilsUnitTest/" />
+        <option name="native-test-flag" value="-P /sdcard/tests/HEVCUtilsUnitTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/libstagefright/tests/HEVC/DynamicConfig.xml b/media/libstagefright/tests/HEVC/DynamicConfig.xml
new file mode 100644
index 0000000..517449c
--- /dev/null
+++ b/media/libstagefright/tests/HEVC/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/HEVCUtils/HEVCUtilsUnitTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/tests/extractorFactory/AndroidTest.xml b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
index 3aa6392..f1d4201 100644
--- a/media/libstagefright/tests/extractorFactory/AndroidTest.xml
+++ b/media/libstagefright/tests/extractorFactory/AndroidTest.xml
@@ -18,14 +18,21 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="ExtractorFactoryTest->/data/local/tmp/ExtractorFactoryTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor.zip?unzip=true"
-            value="/data/local/tmp/ExtractorFactoryTestRes/" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="ExtractorFactoryTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="extractor-1.5" />
+        <option name="dynamic-config-module" value="ExtractorFactoryTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="ExtractorFactoryTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/ExtractorFactoryTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/extractor-1.5/" />
     </test>
 </configuration>
diff --git a/media/libstagefright/tests/extractorFactory/DynamicConfig.xml b/media/libstagefright/tests/extractorFactory/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/libstagefright/tests/extractorFactory/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/tests/writer/AndroidTest.xml b/media/libstagefright/tests/writer/AndroidTest.xml
index cc890fe..0b0eb01 100644
--- a/media/libstagefright/tests/writer/AndroidTest.xml
+++ b/media/libstagefright/tests/writer/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="writerTest->/data/local/tmp/writerTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/WriterTestRes-1.1.zip?unzip=true"
-            value="/data/local/tmp/WriterTestRes/" />
     </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="writerTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="WriterTestRes-1.2" />
+        <option name="dynamic-config-module" value="writerTest" />
+    </target_preparer>
+
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="writerTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/WriterTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/WriterTestRes-1.2/" />
         <option name="native-test-flag" value="-C true" />
     </test>
 </configuration>
diff --git a/media/libstagefright/tests/writer/DynamicConfig.xml b/media/libstagefright/tests/writer/DynamicConfig.xml
new file mode 100644
index 0000000..e6dc502
--- /dev/null
+++ b/media/libstagefright/tests/writer/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/writer/WriterTestRes-1.2.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/timedtext/test/AndroidTest.xml b/media/libstagefright/timedtext/test/AndroidTest.xml
index 3654e23..0d5d79f 100644
--- a/media/libstagefright/timedtext/test/AndroidTest.xml
+++ b/media/libstagefright/timedtext/test/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="TimedTextUnitTest->/data/local/tmp/TimedTextUnitTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest.zip?unzip=true"
-            value="/data/local/tmp/TimedTextUnitTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="TimedTextUnitTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="TimedTextUnitTest-1.0" />
+        <option name="dynamic-config-module" value="TimedTextUnitTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="TimedTextUnitTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTestRes/" />
+        <option name="native-test-flag" value="-P /data/local/tmp/TimedTextUnitTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/libstagefright/timedtext/test/DynamicConfig.xml b/media/libstagefright/timedtext/test/DynamicConfig.xml
new file mode 100644
index 0000000..e36277e
--- /dev/null
+++ b/media/libstagefright/timedtext/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/timedtext/test/TimedTextUnitTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/libstagefright/timedtext/test/fuzzer/Android.bp b/media/libstagefright/timedtext/test/fuzzer/Android.bp
new file mode 100644
index 0000000..6590ebb
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/Android.bp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+cc_library_static {
+    name: "timedtext_fuzz-protos",
+
+    srcs: ["timedtext_fuzz.proto"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: ["libprotobuf-cpp-full"],
+    proto: {
+        type: "full",
+        canonical_path_from_root: false,
+        local_include_dirs: ["."],
+        export_proto_headers: true,
+    },
+}
+
+cc_fuzz {
+    name: "timedtext_fuzzer",
+    srcs: [
+        "timedtext_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_timedtext",
+        "timedtext_fuzz-protos",
+    ],
+    shared_libs: [
+        "libstagefright_foundation",
+        "libprotobuf-cpp-full",
+        "libbinder",
+        "libprotobuf-mutator",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
diff --git a/media/libstagefright/timedtext/test/fuzzer/README.md b/media/libstagefright/timedtext/test/fuzzer/README.md
new file mode 100644
index 0000000..f391ea7
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/README.md
@@ -0,0 +1,23 @@
+# Fuzzer for libstagefright_timedtext
+
+libstagefright_timedtext supports the following parameters:
+1. Flags (parameter name: `flags`)
+2. TimeMs (parameter name: `timeMs`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `flags`   | 1. `TextDescriptions::OUT_OF_BAND_TEXT_SRT` 2.  `TextDescriptions::GLOBAL_DESCRIPTIONS` 3. `TextDescriptions::IN_BAND_TEXT_3GPP` 4. `TextDescriptions::LOCAL_DESCRIPTIONS` | Value chosen from valid values by obtaining index from FuzzedDataProvider|
+| `timeMs`   | `INT_MIN` to `INT_MAX` | Value obtained from FuzzedDataProvider|
+
+
+#### Steps to run
+
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) timedtext_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/timedtext_fuzzer/timedtext_fuzzer
+```
diff --git a/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto
new file mode 100644
index 0000000..4c90278
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzz.proto
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+/*
+ * proto files are used for Structure Aware fuzzing so that fuzzing can be
+ * made more effective.
+ * timedtext_fuzz.proto is used to declare structures, which are used
+ * purely inside timedtext_fuzzer.
+ */
+
+syntax = "proto3";
+
+enum Flag {
+    flag3gppglobal = 0;
+    flag3gpplocal = 1;
+    flagsrtlocal = 2;
+}
+
+enum ChunkType {
+    default = 0;
+    tx3g = 1954034535;
+    styl = 1937013100;
+    krok = 1802661739;
+    hlit = 1751935348;
+    hclr = 1751346290;
+    dlay = 1684824441;
+    href = 1752327526;
+    tbox = 1952608120;
+    blnk = 1651273323;
+    txrp = 1953985136;
+}
+
+message FontRecord {
+    uint32 fontId = 1;
+    repeated uint32 font = 2;
+}
+
+message SRTLocal {
+    repeated uint32 data = 1;
+}
+
+message GPPGlobal {
+    uint64 reservedBytes = 1;
+    uint32 displayFlags = 2;
+    int32 horizontal_vertical_justification = 3;
+    uint32 rgba = 4;
+    int32 textBox = 5;
+    uint32 styleRecordStart = 6;
+    uint32 fontId = 7;
+    uint32 fontStyle = 8;
+    uint32 entryCount = 9;
+    repeated FontRecord fontEntry = 10;
+    uint32 defaultDisparity = 11;
+}
+
+message StyleRecord {
+    uint32 startchar = 1;
+    uint32 font = 2;
+    uint32 rgba = 3;
+}
+
+message TextStyleBox {
+    uint32 count = 1;
+    repeated StyleRecord record = 2;
+}
+
+message HighlightBox {
+    uint32 start = 1;
+    uint32 end = 2;
+}
+
+message HighlightColor {
+    uint32 rgba = 1;
+}
+
+message TextKaraokeBox {
+    uint32 highlightStartTime = 1;
+    uint32 entryCount = 2;
+    repeated uint64 highlightData = 3;
+}
+
+message BoxRecord {
+    uint32 topleft = 1;
+    uint32 bottomright = 2;
+}
+
+message BlinkBox {
+    uint32 charoffset = 1;
+}
+
+message HyperTextBox {
+    uint32 charoffset = 1;
+    uint32 urlLength = 2;
+    repeated uint32 url = 3;
+    uint32 altLength = 4;
+    repeated uint32 altString = 5;
+}
+
+message GPPLocalText {
+    string text = 1;
+}
+
+message GPPLocalFormat {
+    uint64 reservedBytes = 1;
+    oneof formatStyle {
+        TextStyleBox textbox = 2;
+        HighlightBox hltbox = 3;
+        HighlightColor hltcolor = 4;
+        TextKaraokeBox krokbox = 5;
+        uint32 scrollDelay = 6;
+        HyperTextBox hrefBox = 7;
+        BoxRecord boxrecord = 8;
+        BlinkBox blinkBox = 9;
+        uint32 wrapFlag = 10;
+    }
+}
+
+message GPPLocal {
+    GPPLocalText localtext = 1;
+    GPPLocalFormat format = 2;
+}
+
+message TimedText {
+    Flag handle = 1;
+    int32 timeMs = 2;
+    SRTLocal srt = 3;
+    GPPGlobal global = 4;
+    GPPLocal local = 5;
+}
diff --git a/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp
new file mode 100644
index 0000000..da1bdf8
--- /dev/null
+++ b/media/libstagefright/timedtext/test/fuzzer/timedtext_fuzzer.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2022 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 <binder/Parcel.h>
+#include <timedtext/TextDescriptions.h>
+#include <timedtext_fuzz.pb.h>
+#include "fuzzer/FuzzedDataProvider.h"
+#include "src/libfuzzer/libfuzzer_macro.h"
+
+using namespace android;
+constexpr int32_t kTextBytes = 2;
+constexpr int32_t kChunkBytes = 8;
+constexpr int32_t kChunkTypeBytes = 4;
+constexpr int32_t kGlobalTextOffset = 0;
+constexpr size_t kByte3Mask = 0xff000000UL;
+constexpr size_t kByte2Mask = 0x00ff0000UL;
+constexpr size_t kByte1Mask = 0x0000ff00UL;
+constexpr size_t kByte0Mask = 0x000000ffUL;
+
+/**
+ * Sets ChunkSize/ChunkType (uint32_t) in timedtext-description vector<uint8_t>
+ * by extracting each byte from ChunkSize and populating the vector.
+ */
+void setChunkParameter(std::vector<uint8_t>& timedtext, size_t param, size_t paramOffset) {
+    timedtext[paramOffset + 0] = (param & kByte3Mask) >> 24;
+    timedtext[paramOffset + 1] = (param & kByte2Mask) >> 16;
+    timedtext[paramOffset + 2] = (param & kByte1Mask) >> 8;
+    timedtext[paramOffset + 3] = (param & kByte0Mask);
+}
+
+/**
+ * Sets TextLength(uint16_t) in 3GPPLocal-description vector<uint8_t>
+ * by extracting each byte from TextLength and populating the vector.
+ */
+void setTextSize(std::vector<uint8_t>& local3GPPDescription, int32_t textLength) {
+    local3GPPDescription[0] = (textLength & kByte1Mask) >> 8;
+    local3GPPDescription[1] = (textLength & kByte0Mask);
+}
+
+DEFINE_PROTO_FUZZER(const TimedText& input) {
+    switch (input.handle()) {
+        case flag3gppglobal: {
+            size_t gppGlobalByteSize = input.global().ByteSizeLong();
+            if (gppGlobalByteSize) {
+                std::vector<uint8_t> global3GPPDescription(gppGlobalByteSize + kChunkBytes);
+                setChunkParameter(global3GPPDescription, gppGlobalByteSize, kGlobalTextOffset);
+                setChunkParameter(global3GPPDescription, tx3g, kGlobalTextOffset + kChunkTypeBytes);
+                input.global().SerializeToArray(global3GPPDescription.data() + kChunkBytes,
+                                                global3GPPDescription.size());
+                Parcel* parcel = new Parcel();
+                TextDescriptions::getParcelOfDescriptions(
+                        global3GPPDescription.data(), global3GPPDescription.size(),
+                        TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::GLOBAL_DESCRIPTIONS,
+                        input.timems(), parcel);
+                delete parcel;
+            }
+            break;
+        }
+        case flag3gpplocal: {
+            size_t gppLocalByteSize = input.local().ByteSizeLong();
+            if (gppLocalByteSize) {
+                std::vector<uint8_t> local3GPPDescription(gppLocalByteSize + kChunkBytes +
+                                                          kTextBytes);
+                std::string text = input.local().localtext().text();
+                int32_t textLength = text.size();
+                setTextSize(local3GPPDescription, textLength);
+                input.local().localtext().SerializeToArray(local3GPPDescription.data() + kTextBytes,
+                                                           textLength);
+                size_t gppLocalFormatSize = input.local().format().ByteSizeLong();
+                size_t textOffset = textLength + kTextBytes;
+                setChunkParameter(local3GPPDescription, gppLocalFormatSize, textOffset);
+                switch (input.local().format().formatStyle_case()) {
+                    case GPPLocalFormat::FormatStyleCase::kTextbox: {
+                        setChunkParameter(local3GPPDescription, styl, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kHltbox: {
+                        setChunkParameter(local3GPPDescription, hlit, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kHltcolor: {
+                        setChunkParameter(local3GPPDescription, hclr, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kKrokbox: {
+                        setChunkParameter(local3GPPDescription, krok, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kScrollDelay: {
+                        setChunkParameter(local3GPPDescription, dlay, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kHrefBox: {
+                        setChunkParameter(local3GPPDescription, href, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kBoxrecord: {
+                        setChunkParameter(local3GPPDescription, tbox, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kBlinkBox: {
+                        setChunkParameter(local3GPPDescription, blnk, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    case GPPLocalFormat::FormatStyleCase::kWrapFlag: {
+                        setChunkParameter(local3GPPDescription, txrp, textOffset + kChunkTypeBytes);
+                        input.local().format().SerializeToArray(
+                                local3GPPDescription.data() + textOffset + kChunkBytes,
+                                gppLocalFormatSize);
+                        break;
+                    }
+                    default: {
+                        break;
+                    }
+                }
+                Parcel* parcel = new Parcel();
+                TextDescriptions::getParcelOfDescriptions(
+                        local3GPPDescription.data(), local3GPPDescription.size(),
+                        TextDescriptions::IN_BAND_TEXT_3GPP | TextDescriptions::LOCAL_DESCRIPTIONS,
+                        input.timems(), parcel);
+                delete parcel;
+            }
+            break;
+        }
+        case flagsrtlocal: {
+            size_t srtByteSize = input.srt().ByteSizeLong();
+            if (srtByteSize) {
+                std::vector<uint8_t> srtLocalDescription(srtByteSize);
+                input.srt().SerializeToArray(srtLocalDescription.data(),
+                                             srtLocalDescription.size());
+                Parcel* parcel = new Parcel();
+                TextDescriptions::getParcelOfDescriptions(
+                        srtLocalDescription.data(), srtLocalDescription.size(),
+                        TextDescriptions::OUT_OF_BAND_TEXT_SRT |
+                                TextDescriptions::LOCAL_DESCRIPTIONS,
+                        input.timems(), parcel);
+                delete parcel;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+}
diff --git a/media/libstagefright/xmlparser/Android.bp b/media/libstagefright/xmlparser/Android.bp
index afc873c..2f204f9 100644
--- a/media/libstagefright/xmlparser/Android.bp
+++ b/media/libstagefright/xmlparser/Android.bp
@@ -55,4 +55,5 @@
     name: "media_codecs",
     srcs: ["media_codecs.xsd"],
     package_name: "media.codecs",
+    root_elements: ["MediaCodecs"],
 }
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index ecfd85e..93111ec 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -169,7 +169,6 @@
 
   public class XmlParser {
     ctor public XmlParser();
-    method public static media.codecs.Included readIncluded(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static media.codecs.MediaCodecs readMediaCodecs(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static String readText(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static void skip(org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
diff --git a/media/module/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
index cff14ac..569420b 100644
--- a/media/module/bqhelper/GraphicBufferSource.cpp
+++ b/media/module/bqhelper/GraphicBufferSource.cpp
@@ -589,7 +589,7 @@
 
 void GraphicBufferSource::onDataspaceChanged_l(
         android_dataspace dataspace, android_pixel_format pixelFormat) {
-    ALOGD("got buffer with new dataSpace #%x", dataspace);
+    ALOGD("got buffer with new dataSpace %#x", dataspace);
     mLastDataspace = dataspace;
 
     if (ColorUtils::convertDataSpaceToV0(dataspace)) {
diff --git a/media/module/codecs/amrnb/dec/test/AndroidTest.xml b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
index 1a9e678..539fa5c 100644
--- a/media/module/codecs/amrnb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
@@ -13,19 +13,27 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Test module config for Amr-nb Decoder unit test">
+<configuration description="Test module config for Amr-wb Decoder unit test">
     <option name="test-suite-tag" value="AmrnbDecoderTest" />
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="AmrnbDecoderTest->/data/local/tmp/AmrnbDecoderTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true"
-            value="/data/local/tmp/AmrnbDecoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="AmrnbDecoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="AmrnbDecoderTest-1.0" />
+        <option name="dynamic-config-module" value="AmrnbDecoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="AmrnbDecoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/AmrnbDecoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrnbDecoderTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrnb/dec/test/DynamicConfig.xml b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..de81c48
--- /dev/null
+++ b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrnb/enc/test/AndroidTest.xml b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
index 9fe61b1..1509728 100644
--- a/media/module/codecs/amrnb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
@@ -13,19 +13,27 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<configuration description="Test module config for Amr-nb Encoder unit test">
+<configuration description="Test module config for Amr-wb Encoder unit test">
     <option name="test-suite-tag" value="AmrnbEncoderTest" />
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="AmrnbEncoderTest->/data/local/tmp/AmrnbEncoderTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true"
-            value="/data/local/tmp/AmrnbEncoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="AmrnbEncoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="AmrnbEncoderTest-1.0" />
+        <option name="dynamic-config-module" value="AmrnbEncoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="AmrnbEncoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/AmrnbEncoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrnbEncoderTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrnb/enc/test/DynamicConfig.xml b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..b22df38
--- /dev/null
+++ b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrwb/dec/test/AndroidTest.xml b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
index e211a1f..392df03 100644
--- a/media/module/codecs/amrwb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="AmrwbDecoderTest->/data/local/tmp/AmrwbDecoderTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true"
-            value="/data/local/tmp/AmrwbDecoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="AmrwbDecoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="AmrwbDecoderTest-1.0" />
+        <option name="dynamic-config-module" value="AmrwbDecoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="AmrwbDecoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/AmrwbDecoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrwbDecoderTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrwb/dec/test/DynamicConfig.xml b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..d41517f
--- /dev/null
+++ b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/amrwb/enc/test/AndroidTest.xml b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
index 46f147c..8822cb2 100644
--- a/media/module/codecs/amrwb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="AmrwbEncoderTest->/data/local/tmp/AmrwbEncoderTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true"
-            value="/data/local/tmp/AmrwbEncoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="AmrwbEncoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="AmrwbEncoderTest-1.0" />
+        <option name="dynamic-config-module" value="AmrwbEncoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="AmrwbEncoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/AmrwbEncoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrwbEncoderTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrwb/enc/test/DynamicConfig.xml b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..1cf5bf5
--- /dev/null
+++ b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/flac/dec/test/AndroidTest.xml b/media/module/codecs/flac/dec/test/AndroidTest.xml
index bebba8e..015f728 100644
--- a/media/module/codecs/flac/dec/test/AndroidTest.xml
+++ b/media/module/codecs/flac/dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="FlacDecoderTest->/data/local/tmp/FlacDecoderTest/" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/flac/dec/test/FlacDecoder.zip?unzip=true"
-            value="/data/local/tmp/FlacDecoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="FlacDecoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="FlacDecoder-1.0" />
+        <option name="dynamic-config-module" value="FlacDecoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="FlacDecoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/FlacDecoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/FlacDecoder-1.0/" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/codecs/flac/dec/test/DynamicConfig.xml b/media/module/codecs/flac/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/module/codecs/flac/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
index 8bb4d1c..bd620d6 100755
--- a/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
+++ b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
@@ -19,14 +19,22 @@
         <option name="cleanup" value="true" />
         <option name="push" value="Mpeg4H263DecoderTest->/data/local/tmp/Mpeg4H263DecoderTest" />
         <option name="append-bitness" value="true" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true"
-            value="/data/local/tmp/Mpeg4H263DecoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="Mpeg4H263DecoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="Mpeg4H263DecoderTest-1.2" />
+        <option name="dynamic-config-module" value="Mpeg4H263DecoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="Mpeg4H263DecoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263DecoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/Mpeg4H263DecoderTest-1.2/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml b/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..5219361
--- /dev/null
+++ b/media/module/codecs/m4v_h263/dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.2.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
index 5218932..6b352b0 100644
--- a/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
+++ b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="Mpeg4H263EncoderTest->/data/local/tmp/Mpeg4H263EncoderTest/" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true"
-            value="/data/local/tmp/Mpeg4H263EncoderTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="Mpeg4H263EncoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="Mpeg4H263Encoder-1.1" />
+        <option name="dynamic-config-module" value="Mpeg4H263EncoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="Mpeg4H263EncoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/Mpeg4H263EncoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/Mpeg4H263Encoder-1.1/" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml b/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml
new file mode 100644
index 0000000..ceb33ef
--- /dev/null
+++ b/media/module/codecs/m4v_h263/enc/test/DynamicConfig.xml
@@ -0,0 +1,21 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder-1.1.zip
+            </value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/codecs/mp3dec/test/AndroidTest.xml b/media/module/codecs/mp3dec/test/AndroidTest.xml
index 29952eb..d16f152 100644
--- a/media/module/codecs/mp3dec/test/AndroidTest.xml
+++ b/media/module/codecs/mp3dec/test/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="Mp3DecoderTest->/data/local/tmp/Mp3DecoderTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true"
-            value="/data/local/tmp/Mp3DecoderTestRes/" />
+</target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="Mp3DecoderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="Mp3DecoderTest-1.3" />
+        <option name="dynamic-config-module" value="Mp3DecoderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="Mp3DecoderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/Mp3DecoderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/Mp3DecoderTest-1.3/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/mp3dec/test/DynamicConfig.xml b/media/module/codecs/mp3dec/test/DynamicConfig.xml
new file mode 100644
index 0000000..048940b
--- /dev/null
+++ b/media/module/codecs/mp3dec/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.3.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/esds/tests/AndroidTest.xml b/media/module/esds/tests/AndroidTest.xml
index a4fbc7f..87ca58c 100644
--- a/media/module/esds/tests/AndroidTest.xml
+++ b/media/module/esds/tests/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="ESDSTest->/data/local/tmp/ESDSTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/ESDS/ESDSTestRes-1.0.zip?unzip=true"
-            value="/data/local/tmp/ESDSTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="ESDSTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="ESDSTestRes-1.1" />
+        <option name="dynamic-config-module" value="ESDSTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="ESDSTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/ESDSTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/ESDSTestRes-1.1/" />
     </test>
 </configuration>
diff --git a/media/module/esds/tests/DynamicConfig.xml b/media/module/esds/tests/DynamicConfig.xml
new file mode 100644
index 0000000..9718dda
--- /dev/null
+++ b/media/module/esds/tests/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/ESDS/ESDSTestRes-1.1.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/extractors/mp3/VBRISeeker.cpp b/media/module/extractors/mp3/VBRISeeker.cpp
index ca51b88..a50754b 100644
--- a/media/module/extractors/mp3/VBRISeeker.cpp
+++ b/media/module/extractors/mp3/VBRISeeker.cpp
@@ -84,7 +84,7 @@
          scale,
          entrySize);
 
-    if (entrySize > 4) {
+    if (entrySize < 1 || entrySize > 4) {
         ALOGE("invalid VBRI entry size: %zu", entrySize);
         return NULL;
     }
@@ -122,16 +122,13 @@
 
     off64_t offset = post_id3_pos;
     for (size_t i = 0; i < numEntries; ++i) {
-        uint32_t numBytes;
+        uint32_t numBytes = 0;
+        // entrySize is known to be [1..4]
         switch (entrySize) {
             case 1: numBytes = buffer[i]; break;
             case 2: numBytes = U16_AT(buffer + 2 * i); break;
             case 3: numBytes = U24_AT(buffer + 3 * i); break;
-            default:
-            {
-                CHECK_EQ(entrySize, 4u);
-                numBytes = U32_AT(buffer + 4 * i); break;
-            }
+            case 4: numBytes = U32_AT(buffer + 4 * i); break;
         }
 
         numBytes *= scale;
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 1d88785..38cf29d 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -26,7 +26,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <log/log.h>
 #include <utils/Log.h>
 
 #include "AC4Parser.h"
@@ -6501,6 +6500,16 @@
             AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
         }
 
+        void *presentationsData;
+        size_t presentationsSize;
+        if (AMediaFormat_getBuffer(
+                    mFormat, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+                    &presentationsData, &presentationsSize)) {
+            AMediaFormat_setBuffer(
+                    meta, AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO,
+                    presentationsData, presentationsSize);
+        }
+
         ++mCurrentSampleIndex;
 
         *out = mBuffer;
diff --git a/media/module/extractors/tests/AndroidTest.xml b/media/module/extractors/tests/AndroidTest.xml
index fc8152c..22669df 100644
--- a/media/module/extractors/tests/AndroidTest.xml
+++ b/media/module/extractors/tests/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="ExtractorUnitTest->/data/local/tmp/ExtractorUnitTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true"
-            value="/data/local/tmp/ExtractorUnitTestRes/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="ExtractorUnitTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="extractor-1.5" />
+        <option name="dynamic-config-module" value="ExtractorUnitTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="ExtractorUnitTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/ExtractorUnitTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/extractor-1.5/" />
     </test>
 </configuration>
diff --git a/media/module/extractors/tests/DynamicConfig.xml b/media/module/extractors/tests/DynamicConfig.xml
new file mode 100644
index 0000000..0258808
--- /dev/null
+++ b/media/module/extractors/tests/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.5.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/foundation/tests/AVCUtils/AndroidTest.xml b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
index 6a088a8..e30bfbf 100644
--- a/media/module/foundation/tests/AVCUtils/AndroidTest.xml
+++ b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
@@ -18,14 +18,22 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="false" />
         <option name="push" value="AVCUtilsUnitTest->/data/local/tmp/AVCUtilsUnitTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.zip?unzip=true"
-            value="/data/local/tmp/AVCUtilsUnitTest/" />
+    </target_preparer>
+
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="AVCUtilsUnitTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="AVCUtilsUnitTest-1.0" />
+        <option name="dynamic-config-module" value="AVCUtilsUnitTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="AVCUtilsUnitTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/AVCUtilsUnitTest/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AVCUtilsUnitTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/module/foundation/tests/AVCUtils/DynamicConfig.xml b/media/module/foundation/tests/AVCUtils/DynamicConfig.xml
new file mode 100644
index 0000000..e5b8bad
--- /dev/null
+++ b/media/module/foundation/tests/AVCUtils/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value> https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/foundation/tests/OpusHeader/AndroidTest.xml b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
index afee16a..4aa4cd2 100644
--- a/media/module/foundation/tests/OpusHeader/AndroidTest.xml
+++ b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
@@ -18,14 +18,21 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="OpusHeaderTest->/data/local/tmp/OpusHeaderTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true"
-            value="/data/local/tmp/OpusHeaderTestRes/" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="OpusHeaderTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="OpusHeader-1.0" />
+        <option name="dynamic-config-module" value="OpusHeaderTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="OpusHeaderTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/OpusHeaderTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/OpusHeader-1.0/" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/media/module/foundation/tests/OpusHeader/DynamicConfig.xml b/media/module/foundation/tests/OpusHeader/DynamicConfig.xml
new file mode 100644
index 0000000..ebac328
--- /dev/null
+++ b/media/module/foundation/tests/OpusHeader/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+        <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/id3/test/AndroidTest.xml b/media/module/id3/test/AndroidTest.xml
index 50f9253..b169994 100644
--- a/media/module/id3/test/AndroidTest.xml
+++ b/media/module/id3/test/AndroidTest.xml
@@ -18,14 +18,21 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="ID3Test->/data/local/tmp/ID3Test" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true"
-            value="/data/local/tmp/ID3TestRes/" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="ID3Test" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="ID3TestRes-1.3" />
+        <option name="dynamic-config-module" value="ID3Test" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="ID3Test" />
-        <option name="native-test-flag" value="-P /data/local/tmp/ID3TestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/ID3TestRes-1.3/" />
     </test>
 </configuration>
diff --git a/media/module/id3/test/DynamicConfig.xml b/media/module/id3/test/DynamicConfig.xml
new file mode 100644
index 0000000..5ae4fcd
--- /dev/null
+++ b/media/module/id3/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.3.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/metadatautils/test/AndroidTest.xml b/media/module/metadatautils/test/AndroidTest.xml
index d6497f3..ce8c4d6 100644
--- a/media/module/metadatautils/test/AndroidTest.xml
+++ b/media/module/metadatautils/test/AndroidTest.xml
@@ -18,13 +18,21 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="false" />
         <option name="push" value="MetaDataUtilsTest->/data/local/tmp/MetaDataUtilsTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/metadatautils/MetaDataUtilsTestRes-1.0.zip?unzip=true"
-            value="/data/local/tmp/MetaDataUtilsTestRes/" />
     </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="MetaDataUtilsTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="MetaDataUtilsTest-1.1" />
+        <option name="dynamic-config-module" value="MetaDataUtilsTest" />
+    </target_preparer>
+
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="MetaDataUtilsTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/MetaDataUtilsTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/MetaDataUtilsTest-1.1/" />
     </test>
 </configuration>
diff --git a/media/module/metadatautils/test/DynamicConfig.xml b/media/module/metadatautils/test/DynamicConfig.xml
new file mode 100644
index 0000000..9d80bf3
--- /dev/null
+++ b/media/module/metadatautils/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/tests/metadatautils/MetaDataUtilsTestRes-1.1.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/module/mpeg2ts/test/AndroidTest.xml b/media/module/mpeg2ts/test/AndroidTest.xml
index ac1294d..836c9f8 100644
--- a/media/module/mpeg2ts/test/AndroidTest.xml
+++ b/media/module/mpeg2ts/test/AndroidTest.xml
@@ -18,14 +18,21 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="Mpeg2tsUnitTest->/data/local/tmp/Mpeg2tsUnitTest" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true"
-            value="/data/local/tmp/Mpeg2tsUnitTestRes/" />
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="Mpeg2tsUnitTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="Mpeg2tsUnitTest-1.0" />
+        <option name="dynamic-config-module" value="Mpeg2tsUnitTest" />
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="Mpeg2tsUnitTest" />
-        <option name="native-test-flag" value="-P /data/local/tmp/Mpeg2tsUnitTestRes/" />
+        <option name="native-test-flag" value="-P /sdcard/test/Mpeg2tsUnitTest-1.0/" />
     </test>
 </configuration>
diff --git a/media/module/mpeg2ts/test/DynamicConfig.xml b/media/module/mpeg2ts/test/DynamicConfig.xml
new file mode 100644
index 0000000..017a3c6
--- /dev/null
+++ b/media/module/mpeg2ts/test/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest-1.0.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
index 011c38c..e2fe177 100644
--- a/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
+++ b/media/tests/SampleVideoEncoder/app/src/main/java/com/android/media/samplevideoencoder/MediaCodecSurfaceEncoder.java
@@ -90,13 +90,13 @@
         }
 
         String decoderMime = decoderFormat.getString(MediaFormat.KEY_MIME);
-        ArrayList<String> listOfDeocders =
+        ArrayList<String> decoders =
                 MediaCodecBase.selectCodecs(decoderMime, null, null, false, mIsCodecSoftware);
-        if (listOfDeocders.isEmpty()) {
+        if (decoders.isEmpty()) {
             Log.e(TAG, "No suitable decoder found for mime: " + decoderMime);
             return -1;
         }
-        mDecoder = MediaCodec.createByCodecName(listOfDeocders.get(0));
+        mDecoder = MediaCodec.createByCodecName(decoders.get(0));
 
         MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat);
         ArrayList<String> listOfEncoders =
diff --git a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
index 1890661..1b66b01 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/AndroidTest.xml
@@ -14,18 +14,26 @@
      limitations under the License.
 -->
 <configuration description="Runs Media Benchmark Tests">
+    <option name="test-tag" value="MediaBenchmarkTest" />
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
-        <option name="push-file"
-            key="https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark.zip?unzip=true"
-            value="/data/local/tmp/MediaBenchmark/res/" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
-        <option name="cleanup-apks" value="false" />
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+        <option name="target" value="host" />
+        <option name="config-filename" value="MediaBenchmarkTest" />
+        <option name="version" value="1.0"/>
+    </target_preparer>
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
+        <option name="push-all" value="true" />
+        <option name="media-folder-name" value="MediaBenchmarkTest-1.1" />
+        <option name="dynamic-config-module" value="MediaBenchmarkTest" />
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
         <option name="test-file-name" value="MediaBenchmarkTest.apk" />
     </target_preparer>
 
-    <option name="test-tag" value="MediaBenchmarkTest" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.media.benchmark" />
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
diff --git a/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
new file mode 100644
index 0000000..1278f29
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2021 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.
+-->
+
+<dynamicConfig>
+    <entry key="media_files_url">
+            <value>https://storage.googleapis.com/android_media/frameworks/av/media/tests/benchmark/MediaBenchmark-1.1.zip</value>
+    </entry>
+</dynamicConfig>
diff --git a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
index 24dbccc..2bef254 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
+++ b/media/tests/benchmark/MediaBenchmarkTest/res/values/strings.xml
@@ -1,4 +1,4 @@
 <resources>
-    <string name="input_file_path">/data/local/tmp/MediaBenchmark/res/</string>
+    <string name="input_file_path">/sdcard/test/MediaBenchmarkTest-1.1/</string>
     <string name="output_file_path">/data/local/tmp/MediaBenchmark/output/</string>
 </resources>
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index f1797e6..90b4057 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -146,27 +146,13 @@
         "AudioFlinger.cpp",
         "AudioHwDevice.cpp",
         "AudioStreamOut.cpp",
-        "AudioWatchdog.cpp",
-        "BufLog.cpp",
         "DeviceEffectManager.cpp",
         "Effects.cpp",
-        "FastCapture.cpp",
-        "FastCaptureDumpState.cpp",
-        "FastCaptureState.cpp",
-        "FastMixer.cpp",
-        "FastMixerDumpState.cpp",
-        "FastMixerState.cpp",
-        "FastThread.cpp",
-        "FastThreadDumpState.cpp",
-        "FastThreadState.cpp",
-        "NBAIO_Tee.cpp",
         "PatchPanel.cpp",
         "PropertyUtils.cpp",
         "SpdifStreamOut.cpp",
-        "StateQueue.cpp",
         "Threads.cpp",
         "Tracks.cpp",
-        "TypedLogger.cpp",
     ],
 
     include_dirs: [
@@ -180,6 +166,9 @@
         "av-types-aidl-cpp",
         "effect-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudioflinger_fastpath",
+        "libaudioflinger_timing",
+        "libaudioflinger_utils",
         "libaudiofoundation",
         "libaudiohal",
         "libaudioprocessing",
@@ -207,7 +196,6 @@
 
     static_libs: [
         "libcpustats",
-        "libsndfile",
         "libpermission",
     ],
 
@@ -223,7 +211,6 @@
     ],
 
     cflags: [
-        "-DSTATE_QUEUE_INSTANTIATIONS=\"StateQueueInstantiations.cpp\"",
         "-fvisibility=hidden",
         "-Werror",
         "-Wall",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0f5021b..4f1d554 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -58,7 +58,6 @@
 #include <audiomanager/AudioManager.h>
 
 #include "AudioFlinger.h"
-#include "NBAIO_Tee.h"
 #include "PropertyUtils.h"
 
 #include <media/AudioResamplerPublic.h>
@@ -86,9 +85,8 @@
 #include <private/android_filesystem_config.h>
 
 //#define BUFLOG_NDEBUG 0
-#include <BufLog.h>
-
-#include "TypedLogger.h"
+#include <afutils/BufLog.h>
+#include <afutils/TypedLogger.h>
 
 // ----------------------------------------------------------------------------
 
@@ -111,6 +109,7 @@
 using media::IEffectClient;
 using media::audio::common::AudioMMapPolicyInfo;
 using media::audio::common::AudioMMapPolicyType;
+using media::audio::common::AudioMode;
 using android::content::AttributionSourceState;
 using android::detail::AudioHalVersionInfo;
 
@@ -235,6 +234,7 @@
 BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
 BINDER_METHOD_ENTRY(isBluetoothVariableLatencyEnabled) \
 BINDER_METHOD_ENTRY(supportsBluetoothVariableLatency) \
+BINDER_METHOD_ENTRY(getAudioPolicyConfig) \
 
 // singleton for Binder Method Statistics for IAudioFlinger
 static auto& getIAudioFlingerStatistics() {
@@ -1234,18 +1234,19 @@
         }
 
         // Look for sync events awaiting for a session to be used.
-        for (size_t i = 0; i < mPendingSyncEvents.size(); i++) {
-            if (mPendingSyncEvents[i]->triggerSession() == sessionId) {
-                if (thread->isValidSyncEvent(mPendingSyncEvents[i])) {
+        for (auto it = mPendingSyncEvents.begin(); it != mPendingSyncEvents.end();) {
+            if ((*it)->triggerSession() == sessionId) {
+                if (thread->isValidSyncEvent(*it)) {
                     if (lStatus == NO_ERROR) {
-                        (void) track->setSyncEvent(mPendingSyncEvents[i]);
+                        (void) track->setSyncEvent(*it);
                     } else {
-                        mPendingSyncEvents[i]->cancel();
+                        (*it)->cancel();
                     }
-                    mPendingSyncEvents.removeAt(i);
-                    i--;
+                    it = mPendingSyncEvents.erase(it);
+                    continue;
                 }
             }
+            ++it;
         }
         if ((output.flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == AUDIO_OUTPUT_FLAG_HW_AV_SYNC) {
             setAudioHwSyncForSession_l(thread, sessionId);
@@ -2538,6 +2539,47 @@
 
 // ----------------------------------------------------------------------------
 
+status_t AudioFlinger::getAudioPolicyConfig(media::AudioPolicyConfig *config)
+{
+    if (config == nullptr) {
+        return BAD_VALUE;
+    }
+    Mutex::Autolock _l(mLock);
+    AutoMutex lock(mHardwareLock);
+    RETURN_STATUS_IF_ERROR(
+            mDevicesFactoryHal->getSurroundSoundConfig(&config->surroundSoundConfig));
+    RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getEngineConfig(&config->engineConfig));
+    std::vector<std::string> hwModuleNames;
+    RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getDeviceNames(&hwModuleNames));
+    std::set<AudioMode> allSupportedModes;
+    for (const auto& name : hwModuleNames) {
+        AudioHwDevice* module = loadHwModule_l(name.c_str());
+        if (module == nullptr) continue;
+        media::AudioHwModule aidlModule;
+        if (module->hwDevice()->getAudioPorts(&aidlModule.ports) == OK &&
+                module->hwDevice()->getAudioRoutes(&aidlModule.routes) == OK) {
+            aidlModule.handle = module->handle();
+            aidlModule.name = module->moduleName();
+            config->modules.push_back(std::move(aidlModule));
+        }
+        std::vector<AudioMode> supportedModes;
+        if (module->hwDevice()->getSupportedModes(&supportedModes) == OK) {
+            allSupportedModes.insert(supportedModes.begin(), supportedModes.end());
+        }
+    }
+    if (!allSupportedModes.empty()) {
+        config->supportedModes.insert(config->supportedModes.end(),
+                allSupportedModes.begin(), allSupportedModes.end());
+    } else {
+        ALOGW("%s: The HAL does not provide telephony functionality", __func__);
+        config->supportedModes = { media::audio::common::AudioMode::NORMAL,
+            media::audio::common::AudioMode::RINGTONE,
+            media::audio::common::AudioMode::IN_CALL,
+            media::audio::common::AudioMode::IN_COMMUNICATION };
+    }
+    return OK;
+}
+
 audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
 {
     if (name == NULL) {
@@ -2548,16 +2590,17 @@
     }
     Mutex::Autolock _l(mLock);
     AutoMutex lock(mHardwareLock);
-    return loadHwModule_l(name);
+    AudioHwDevice* module = loadHwModule_l(name);
+    return module != nullptr ? module->handle() : AUDIO_MODULE_HANDLE_NONE;
 }
 
 // loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
-audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
+AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
 {
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
             ALOGW("loadHwModule() module %s already loaded", name);
-            return mAudioHwDevs.keyAt(i);
+            return mAudioHwDevs.valueAt(i);
         }
     }
 
@@ -2566,7 +2609,7 @@
     int rc = mDevicesFactoryHal->openDevice(name, &dev);
     if (rc) {
         ALOGE("loadHwModule() error %d loading module %s", rc, name);
-        return AUDIO_MODULE_HANDLE_NONE;
+        return nullptr;
     }
 
     mHardwareStatus = AUDIO_HW_INIT;
@@ -2574,7 +2617,7 @@
     mHardwareStatus = AUDIO_HW_IDLE;
     if (rc) {
         ALOGE("loadHwModule() init check error %d for module %s", rc, name);
-        return AUDIO_MODULE_HANDLE_NONE;
+        return nullptr;
     }
 
     // Check and cache this HAL's level of support for master mute and master
@@ -2648,8 +2691,7 @@
 
     ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);
 
-    return handle;
-
+    return audioDevice;
 }
 
 // ----------------------------------------------------------------------------
@@ -2898,14 +2940,6 @@
         return nullptr;
     }
 
-#ifndef MULTICHANNEL_EFFECT_CHAIN
-    if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
-        ALOGE("openOutput_l() cannot create spatializer thread "
-                "without #define MULTICHANNEL_EFFECT_CHAIN");
-        return nullptr;
-    }
-#endif
-
     mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
 
     // FOR TESTING ONLY:
@@ -3876,15 +3910,16 @@
     track->setTeePatches(std::move(teePatches));
 }
 
-sp<AudioFlinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
+sp<audioflinger::SyncEvent> AudioFlinger::createSyncEvent(AudioSystem::sync_event_t type,
                                     audio_session_t triggerSession,
                                     audio_session_t listenerSession,
-                                    sync_event_callback_t callBack,
+                                    const audioflinger::SyncEventCallback& callBack,
                                     const wp<RefBase>& cookie)
 {
     Mutex::Autolock _l(mLock);
 
-    sp<SyncEvent> event = new SyncEvent(type, triggerSession, listenerSession, callBack, cookie);
+    auto event = sp<audioflinger::SyncEvent>::make(
+            type, triggerSession, listenerSession, callBack, cookie);
     status_t playStatus = NAME_NOT_FOUND;
     status_t recStatus = NAME_NOT_FOUND;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -3900,7 +3935,7 @@
         }
     }
     if (playStatus == NAME_NOT_FOUND || recStatus == NAME_NOT_FOUND) {
-        mPendingSyncEvents.add(event);
+        mPendingSyncEvents.emplace_back(event);
     } else {
         ALOGV("createSyncEvent() invalid event %d", event->type());
         event.clear();
@@ -4648,6 +4683,7 @@
         case TransactionCode::SET_DEVICE_CONNECTED_STATE:
         case TransactionCode::SET_REQUESTED_LATENCY_MODE:
         case TransactionCode::GET_SUPPORTED_LATENCY_MODES:
+        case TransactionCode::GET_AUDIO_POLICY_CONFIG:
             ALOGW("%s: transaction %d received from PID %d",
                   __func__, code, IPCThreadState::self()->getCallingPid());
             // return status only for non void methods
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c2493ec..6d422b6 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -78,20 +78,25 @@
 #include <mediautils/Synchronization.h>
 #include <mediautils/ThreadSnapshot.h>
 
+#include <afutils/AudioWatchdog.h>
+#include <afutils/NBAIO_Tee.h>
+
 #include <audio_utils/clock.h>
 #include <audio_utils/FdToString.h>
 #include <audio_utils/LinearMap.h>
 #include <audio_utils/SimpleLog.h>
 #include <audio_utils/TimestampVerifier.h>
 
-#include "FastCapture.h"
-#include "FastMixer.h"
+#include <timing/MonotonicFrameCounter.h>
+#include <timing/SyncEvent.h>
+#include <timing/SynchronizedRecordState.h>
+
+#include <fastpath/FastCapture.h>
+#include <fastpath/FastMixer.h>
 #include <media/nbaio/NBAIO.h>
-#include "AudioWatchdog.h"
 #include "AudioStreamOut.h"
 #include "SpdifStreamOut.h"
 #include "AudioHwDevice.h"
-#include "NBAIO_Tee.h"
 #include "ThreadMetrics.h"
 #include "TrackMetrics.h"
 
@@ -131,6 +136,7 @@
 
 class AudioFlinger : public AudioFlingerServerAdapter::Delegate
 {
+    friend class sp<AudioFlinger>;
 public:
     static void instantiate() ANDROID_API;
 
@@ -308,6 +314,8 @@
 
     virtual status_t supportsBluetoothVariableLatency(bool* support);
 
+    virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+
     status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
         const std::function<status_t()>& delegate) override;
 
@@ -369,47 +377,10 @@
 
     static inline std::atomic<AudioFlinger *> gAudioFlinger = nullptr;
 
-    class SyncEvent;
-
-    typedef void (*sync_event_callback_t)(const wp<SyncEvent>& event) ;
-
-    class SyncEvent : public RefBase {
-    public:
-        SyncEvent(AudioSystem::sync_event_t type,
-                  audio_session_t triggerSession,
-                  audio_session_t listenerSession,
-                  sync_event_callback_t callBack,
-                  const wp<RefBase>& cookie)
-        : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
-          mCallback(callBack), mCookie(cookie)
-        {}
-
-        virtual ~SyncEvent() {}
-
-        void trigger() {
-            Mutex::Autolock _l(mLock);
-            if (mCallback) mCallback(wp<SyncEvent>(this));
-        }
-        bool isCancelled() const { Mutex::Autolock _l(mLock); return (mCallback == NULL); }
-        void cancel() { Mutex::Autolock _l(mLock); mCallback = NULL; }
-        AudioSystem::sync_event_t type() const { return mType; }
-        audio_session_t triggerSession() const { return mTriggerSession; }
-        audio_session_t listenerSession() const { return mListenerSession; }
-        wp<RefBase> cookie() const { return mCookie; }
-
-    private:
-          const AudioSystem::sync_event_t mType;
-          const audio_session_t mTriggerSession;
-          const audio_session_t mListenerSession;
-          sync_event_callback_t mCallback;
-          const wp<RefBase> mCookie;
-          mutable Mutex mLock;
-    };
-
-    sp<SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+    sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
                                         audio_session_t triggerSession,
                                         audio_session_t listenerSession,
-                                        sync_event_callback_t callBack,
+                                        const audioflinger::SyncEventCallback& callBack,
                                         const wp<RefBase>& cookie);
 
     bool        btNrecIsOff() const { return mBtNrecIsOff.load(); }
@@ -626,13 +597,6 @@
     };
 
     // --- PlaybackThread ---
-#ifdef FLOAT_EFFECT_CHAIN
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_FLOAT
-using effect_buffer_t = float;
-#else
-#define EFFECT_BUFFER_FORMAT AUDIO_FORMAT_PCM_16_BIT
-using effect_buffer_t = int16_t;
-#endif
 
 #include "Threads.h"
 
@@ -968,10 +932,10 @@
                 float       masterVolume_l() const;
                 float       getMasterBalance_l() const;
                 bool        masterMute_l() const;
-                audio_module_handle_t loadHwModule_l(const char *name);
+                AudioHwDevice* loadHwModule_l(const char *name);
 
-                Vector < sp<SyncEvent> > mPendingSyncEvents; // sync events awaiting for a session
-                                                             // to be created
+                // sync events awaiting for a session to be created.
+                std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
 
                 // Effect chains without a valid thread
                 DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
diff --git a/services/audioflinger/AudioWatchdog.h b/services/audioflinger/AudioWatchdog.h
deleted file mode 100644
index 7b69fc6..0000000
--- a/services/audioflinger/AudioWatchdog.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-// The watchdog thread runs periodically.  It has two functions:
-//   (a) verify that adequate CPU time is available, and log
-//       as soon as possible when there appears to be a CPU shortage
-//   (b) monitor the other threads [not yet implemented]
-
-#ifndef AUDIO_WATCHDOG_H
-#define AUDIO_WATCHDOG_H
-
-#include <time.h>
-#include <utils/Thread.h>
-
-namespace android {
-
-// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
-// The usual caveats about atomicity of information apply.
-struct AudioWatchdogDump {
-    AudioWatchdogDump() : mUnderruns(0), mLogs(0), mMostRecent(0) { }
-    /*virtual*/ ~AudioWatchdogDump() { }
-    uint32_t mUnderruns;    // total number of underruns
-    uint32_t mLogs;         // total number of log messages
-    time_t   mMostRecent;   // time of most recent log
-    void     dump(int fd);  // should only be called on a stable copy, not the original
-};
-
-class AudioWatchdog : public Thread {
-
-public:
-    explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/), mPaused(false),
-            mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2),
-            // mOldTs
-            // mLogTs initialized below
-            mOldTsValid(false), mUnderruns(0), mLogs(0), mDump(&mDummyDump)
-        {
-#define MIN_TIME_BETWEEN_LOGS_SEC 60
-            // force an immediate log on first underrun
-            mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
-            mLogTs.tv_nsec = 0;
-        }
-    virtual         ~AudioWatchdog() { }
-
-     // Do not call Thread::requestExitAndWait() without first calling requestExit().
-    // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
-    virtual void        requestExit();
-
-    // FIXME merge API and implementation with AudioTrackThread
-    void            pause();        // suspend thread from execution at next loop boundary
-    void            resume();       // allow thread to execute, if not requested to exit
-
-    // Where to store the dump, or NULL to not update
-    void            setDump(AudioWatchdogDump* dump);
-
-private:
-    virtual bool    threadLoop();
-
-    Mutex           mMyLock;        // Thread::mLock is private
-    Condition       mMyCond;        // Thread::mThreadExitedCondition is private
-    bool            mPaused;        // whether thread is currently paused
-
-    uint32_t        mPeriodNs;      // nominal period
-    uint32_t        mMaxCycleNs;    // maximum allowed time of one cycle before declaring underrun
-    struct timespec mOldTs;         // monotonic time when threadLoop last ran
-    struct timespec mLogTs;         // time since last log
-    bool            mOldTsValid;    // whether mOldTs is valid
-    uint32_t        mUnderruns;     // total number of underruns
-    uint32_t        mLogs;          // total number of logs
-    AudioWatchdogDump*  mDump;      // where to store the dump, always non-NULL
-    AudioWatchdogDump   mDummyDump; // default area for dump in case setDump() is not called
-};
-
-}   // namespace android
-
-#endif  // AUDIO_WATCHDOG_H
diff --git a/services/audioflinger/Configuration.h b/services/audioflinger/Configuration.h
index ede8e3f..845697a 100644
--- a/services/audioflinger/Configuration.h
+++ b/services/audioflinger/Configuration.h
@@ -41,15 +41,4 @@
 // uncomment to log CPU statistics every n wall clock seconds
 //#define DEBUG_CPU_USAGE 10
 
-// define FLOAT_EFFECT_CHAIN to request float effects (falls back to int16_t if unavailable)
-#define FLOAT_EFFECT_CHAIN
-
-#ifdef FLOAT_EFFECT_CHAIN
-// define FLOAT_AUX to process aux effect buffers in float (FLOAT_EFFECT_CHAIN must be defined)
-#define FLOAT_AUX
-
-// define MULTICHANNEL_EFFECT_CHAIN to allow multichannel effects (FLOAT_EFFECT_CHAIN defined)
-#define MULTICHANNEL_EFFECT_CHAIN
-#endif
-
 #endif // ANDROID_AUDIOFLINGER_CONFIGURATION_H
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index e912bff..6963bb9 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -572,9 +572,7 @@
       mOffloaded(false),
       mAddedToHal(false),
       mIsOutput(false)
-#ifdef FLOAT_EFFECT_CHAIN
       , mSupportsFloat(false)
-#endif
 {
     ALOGV("Constructor %p pinned %d", this, pinned);
     int lStatus;
@@ -693,31 +691,16 @@
                             mConfig.inputCfg.buffer.frameCount,
                             mConfig.outputCfg.buffer.frameCount);
     const auto accumulateInputToOutput = [this, safeInputOutputSampleCount]() {
-#ifdef FLOAT_EFFECT_CHAIN
         accumulate_float(
                 mConfig.outputCfg.buffer.f32,
                 mConfig.inputCfg.buffer.f32,
                 safeInputOutputSampleCount);
-#else
-        accumulate_i16(
-                mConfig.outputCfg.buffer.s16,
-                mConfig.inputCfg.buffer.s16,
-                safeInputOutputSampleCount);
-#endif
     };
     const auto copyInputToOutput = [this, safeInputOutputSampleCount]() {
-#ifdef FLOAT_EFFECT_CHAIN
         memcpy(
                 mConfig.outputCfg.buffer.f32,
                 mConfig.inputCfg.buffer.f32,
                 safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.f32));
-
-#else
-        memcpy(
-                mConfig.outputCfg.buffer.s16,
-                mConfig.inputCfg.buffer.s16,
-                safeInputOutputSampleCount * sizeof(*mConfig.outputCfg.buffer.s16));
-#endif
     };
 
     if (isProcessEnabled()) {
@@ -726,35 +709,14 @@
             if (auxType) {
                 // We overwrite the aux input buffer here and clear after processing.
                 // aux input is always mono.
-#ifdef FLOAT_EFFECT_CHAIN
-                if (mSupportsFloat) {
-#ifndef FLOAT_AUX
-                    // Do in-place float conversion for auxiliary effect input buffer.
-                    static_assert(sizeof(float) <= sizeof(int32_t),
-                            "in-place conversion requires sizeof(float) <= sizeof(int32_t)");
 
-                    memcpy_to_float_from_q4_27(
-                            mConfig.inputCfg.buffer.f32,
-                            mConfig.inputCfg.buffer.s32,
-                            mConfig.inputCfg.buffer.frameCount);
-#endif // !FLOAT_AUX
-                } else
-#endif // FLOAT_EFFECT_CHAIN
-                {
-#ifdef FLOAT_AUX
+                if (!mSupportsFloat) {
                     memcpy_to_i16_from_float(
                             mConfig.inputCfg.buffer.s16,
                             mConfig.inputCfg.buffer.f32,
                             mConfig.inputCfg.buffer.frameCount);
-#else
-                    memcpy_to_i16_from_q4_27(
-                            mConfig.inputCfg.buffer.s16,
-                            mConfig.inputCfg.buffer.s32,
-                            mConfig.inputCfg.buffer.frameCount);
-#endif
                 }
             }
-#ifdef FLOAT_EFFECT_CHAIN
             sp<EffectBufferHalInterface> inBuffer = mInBuffer;
             sp<EffectBufferHalInterface> outBuffer = mOutBuffer;
 
@@ -801,9 +763,7 @@
                     outBuffer = mOutConversionBuffer;
                 }
             }
-#endif
             ret = mEffectInterface->process();
-#ifdef FLOAT_EFFECT_CHAIN
             if (!mSupportsFloat) { // convert output int16_t back to float.
                 sp<EffectBufferHalInterface> target =
                         mOutChannelCountRequested != outChannelCount
@@ -820,11 +780,8 @@
                         sizeof(float),
                         sizeof(float) * outChannelCount * mConfig.outputCfg.buffer.frameCount);
             }
-#endif
         } else {
-#ifdef FLOAT_EFFECT_CHAIN
             data_bypass:
-#endif
             if (!auxType  /* aux effects do not require data bypass */
                     && mConfig.inputCfg.buffer.raw != mConfig.outputCfg.buffer.raw) {
                 if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
@@ -843,13 +800,8 @@
 
         // clear auxiliary effect input buffer for next accumulation
         if (auxType) {
-#ifdef FLOAT_AUX
             const size_t size =
                     mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(float);
-#else
-            const size_t size =
-                    mConfig.inputCfg.buffer.frameCount * inChannelCount * sizeof(int32_t);
-#endif
             memset(mConfig.inputCfg.buffer.raw, 0, size);
         }
     } else if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT &&
@@ -904,23 +856,6 @@
             ALOGV("Overriding auxiliary effect input channels %#x as MONO",
                     mConfig.inputCfg.channels);
         }
-#ifndef MULTICHANNEL_EFFECT_CHAIN
-        if (mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) {
-            mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
-            ALOGV("Overriding auxiliary effect output channels %#x as STEREO",
-                    mConfig.outputCfg.channels);
-        }
-#endif
-    } else {
-#ifndef MULTICHANNEL_EFFECT_CHAIN
-        // TODO: Update this logic when multichannel effects are implemented.
-        // For offloaded tracks consider mono output as stereo for proper effect initialization
-        if (channelMask == AUDIO_CHANNEL_OUT_MONO) {
-            mConfig.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
-            mConfig.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
-            ALOGV("Overriding effect input and output as STEREO");
-        }
-#endif
     }
     if (isHapticGenerator()) {
         audio_channel_mask_t hapticChannelMask = callback->hapticChannelMask();
@@ -932,8 +867,8 @@
     mOutChannelCountRequested =
             audio_channel_count_from_out_mask(mConfig.outputCfg.channels);
 
-    mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
-    mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
+    mConfig.inputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+    mConfig.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
 
     // Don't use sample rate for thread if effect isn't offloadable.
     if (callback->isOffloadOrDirect() && !isOffloaded()) {
@@ -981,7 +916,6 @@
         status = cmdStatus;
     }
 
-#ifdef MULTICHANNEL_EFFECT_CHAIN
     if (status != NO_ERROR &&
             mIsOutput &&
             (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
@@ -1006,9 +940,7 @@
             status = cmdStatus;
         }
     }
-#endif
 
-#ifdef FLOAT_EFFECT_CHAIN
     if (status == NO_ERROR) {
         mSupportsFloat = true;
     }
@@ -1033,7 +965,6 @@
             ALOGE("%s failed %d with int16_t (as well as float)", __func__, status);
         }
     }
-#endif
 
     if (status == NO_ERROR) {
         // Establish Buffer strategy
@@ -1347,7 +1278,6 @@
     mInBuffer = buffer;
     mEffectInterface->setInBuffer(buffer);
 
-#ifdef FLOAT_EFFECT_CHAIN
     // aux effects do in place conversion to float - we don't allocate mInConversionBuffer.
     // Theoretically insert effects can also do in-place conversions (destroying
     // the original buffer) when the output buffer is identical to the input buffer,
@@ -1379,7 +1309,6 @@
             ALOGE("%s cannot create mInConversionBuffer", __func__);
         }
     }
-#endif
 }
 
 void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
@@ -1395,7 +1324,6 @@
     mOutBuffer = buffer;
     mEffectInterface->setOutBuffer(buffer);
 
-#ifdef FLOAT_EFFECT_CHAIN
     // Note: Any effect that does not accumulate does not need mOutConversionBuffer and
     // can do in-place conversion from int16_t to float.  We don't optimize here.
     const uint32_t outChannelCount =
@@ -1423,7 +1351,6 @@
             ALOGE("%s cannot create mOutConversionBuffer", __func__);
         }
     }
-#endif
 }
 
 status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
@@ -1719,15 +1646,12 @@
             mConfig.outputCfg.format,
             formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
 
-#ifdef FLOAT_EFFECT_CHAIN
-
     result.appendFormat("\t\t- HAL buffers:\n"
             "\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
             dumpInOutBuffer(true /* isInput */, mInBuffer).c_str(),
             dumpInOutBuffer(true /* isInput */, mInConversionBuffer).c_str(),
             dumpInOutBuffer(false /* isInput */, mOutBuffer).c_str(),
             dumpInOutBuffer(false /* isInput */, mOutConversionBuffer).c_str());
-#endif
 
     write(fd, result.string(), result.length());
 
@@ -2253,7 +2177,7 @@
     if (mInBuffer == NULL) {
         return;
     }
-    const size_t frameSize = audio_bytes_per_sample(EFFECT_BUFFER_FORMAT)
+    const size_t frameSize = audio_bytes_per_sample(AUDIO_FORMAT_PCM_FLOAT)
             * mEffectCallback->inChannelCount(mEffects[0]->id());
 
     memset(mInBuffer->audioBuffer()->raw, 0, mEffectCallback->frameCount() * frameSize);
@@ -2354,13 +2278,9 @@
         // calling the process in effect engine
         size_t numSamples = mEffectCallback->frameCount();
         sp<EffectBufferHalInterface> halBuffer;
-#ifdef FLOAT_EFFECT_CHAIN
+
         status_t result = mEffectCallback->allocateHalBuffer(
                 numSamples * sizeof(float), &halBuffer);
-#else
-        status_t result = mEffectCallback->allocateHalBuffer(
-                numSamples * sizeof(int32_t), &halBuffer);
-#endif
         if (result != OK) return result;
 
         effect->configure();
@@ -2527,7 +2447,8 @@
 
             // make sure the input buffer configuration for the new first effect in the chain
             // is updated if needed (can switch from HAL channel mask to mixer channel mask)
-            if (i == 0 && size > 1) {
+            if (type != EFFECT_FLAG_TYPE_AUXILIARY // TODO(b/284522658) breaks for aux FX, why?
+                    && i == 0 && size > 1) {
                 mEffects[0]->configure();
                 mEffects[0]->setInBuffer(mInBuffer);
                 mEffects[0]->updateAccessMode();      // reconfig if neeeded.
@@ -3355,8 +3276,18 @@
     ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
             __func__, port->type, port->ext.device.type,
             port->ext.device.address, port->id, patch.isSoftware());
-    if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType
-        || port->ext.device.address != mDevice.address()) {
+    if (port->type != AUDIO_PORT_TYPE_DEVICE || port->ext.device.type != mDevice.mType ||
+        port->ext.device.address != mDevice.address()) {
+        return NAME_NOT_FOUND;
+    }
+    if (((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) &&
+        (audio_port_config_has_input_direction(port))) {
+        ALOGI("%s don't create postprocessing effect on record port", __func__);
+        return NAME_NOT_FOUND;
+    }
+    if (((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) &&
+        (!audio_port_config_has_input_direction(port))) {
+        ALOGI("%s don't create preprocessing effect on playback port", __func__);
         return NAME_NOT_FOUND;
     }
     status_t status = NAME_NOT_FOUND;
@@ -3408,6 +3339,7 @@
     } else {
         status = BAD_VALUE;
     }
+
     if (status == NO_ERROR || status == ALREADY_EXISTS) {
         Status bs;
         if (isEnabled()) {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index bad86bc..e1a76fc 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -322,13 +322,11 @@
     bool     mAddedToHal;           // effect has been added to the audio HAL
     bool     mIsOutput;             // direction of the AF thread
 
-#ifdef FLOAT_EFFECT_CHAIN
     bool    mSupportsFloat;         // effect supports float processing
     sp<EffectBufferHalInterface> mInConversionBuffer;  // Buffers for HAL conversion if needed.
     sp<EffectBufferHalInterface> mOutConversionBuffer;
     uint32_t mInChannelCountRequested;
     uint32_t mOutChannelCountRequested;
-#endif
 
     class AutoLockReentrant {
     public:
@@ -493,14 +491,14 @@
     void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
         mInBuffer = buffer;
     }
-    effect_buffer_t *inBuffer() const {
-        return mInBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mInBuffer->ptr()) : NULL;
+    float *inBuffer() const {
+        return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
     }
     void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
         mOutBuffer = buffer;
     }
-    effect_buffer_t *outBuffer() const {
-        return mOutBuffer != 0 ? reinterpret_cast<effect_buffer_t*>(mOutBuffer->ptr()) : NULL;
+    float *outBuffer() const {
+        return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
     }
 
     void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
diff --git a/services/audioflinger/FastCapture.h b/services/audioflinger/FastCapture.h
deleted file mode 100644
index c3817c0..0000000
--- a/services/audioflinger/FastCapture.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_H
-
-#include "FastThread.h"
-#include "StateQueue.h"
-#include "FastCaptureState.h"
-#include "FastCaptureDumpState.h"
-
-namespace android {
-
-typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
-
-class FastCapture : public FastThread {
-
-public:
-            FastCapture();
-    virtual ~FastCapture();
-
-            FastCaptureStateQueue*  sq();
-
-private:
-            FastCaptureStateQueue   mSQ;
-
-    // callouts
-    virtual const FastThreadState *poll();
-    virtual void setNBLogWriter(NBLog::Writer *logWriter);
-    virtual void onIdle();
-    virtual void onExit();
-    virtual bool isSubClassCommand(FastThreadState::Command command);
-    virtual void onStateChange();
-    virtual void onWork();
-
-    static const FastCaptureState sInitial;
-
-    FastCaptureState    mPreIdle;   // copy of state before we went into idle
-    // FIXME by renaming, could pull up many of these to FastThread
-    NBAIO_Source*       mInputSource;
-    int                 mInputSourceGen;
-    NBAIO_Sink*         mPipeSink;
-    int                 mPipeSinkGen;
-    void*               mReadBuffer;
-    ssize_t             mReadBufferState;   // number of initialized frames in readBuffer,
-                                            // or -1 to clear
-    NBAIO_Format        mFormat;
-    unsigned            mSampleRate;
-    FastCaptureDumpState mDummyFastCaptureDumpState;
-    uint32_t            mTotalNativeFramesRead; // copied to dumpState->mFramesRead
-
-};  // class FastCapture
-
-}   // namespace android
-
-#endif  // ANDROID_AUDIO_FAST_CAPTURE_H
diff --git a/services/audioflinger/FastThread.h b/services/audioflinger/FastThread.h
deleted file mode 100644
index 2f0f73f..0000000
--- a/services/audioflinger/FastThread.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#ifndef ANDROID_AUDIO_FAST_THREAD_H
-#define ANDROID_AUDIO_FAST_THREAD_H
-
-#include "Configuration.h"
-#ifdef CPU_FREQUENCY_STATISTICS
-#include <cpustats/ThreadCpuUsage.h>
-#endif
-#include <utils/Thread.h>
-#include "FastThreadState.h"
-
-namespace android {
-
-// FastThread is the common abstract base class of FastMixer and FastCapture
-class FastThread : public Thread {
-
-public:
-            FastThread(const char *cycleMs, const char *loadUs);
-    virtual ~FastThread();
-
-private:
-    // implement Thread::threadLoop()
-    virtual bool threadLoop();
-
-protected:
-    // callouts to subclass in same lexical order as they were in original FastMixer.cpp
-    // FIXME need comments
-    virtual const FastThreadState *poll() = 0;
-    virtual void setNBLogWriter(NBLog::Writer *logWriter __unused) { }
-    virtual void onIdle() = 0;
-    virtual void onExit() = 0;
-    virtual bool isSubClassCommand(FastThreadState::Command command) = 0;
-    virtual void onStateChange() = 0;
-    virtual void onWork() = 0;
-
-    // FIXME these former local variables need comments
-    const FastThreadState*  mPrevious;
-    const FastThreadState*  mCurrent;
-    struct timespec mOldTs;
-    bool            mOldTsValid;
-    long            mSleepNs;       // -1: busy wait, 0: sched_yield, > 0: nanosleep
-    long            mPeriodNs;      // expected period; the time required to render one mix buffer
-    long            mUnderrunNs;    // underrun likely when write cycle is greater than this value
-    long            mOverrunNs;     // overrun likely when write cycle is less than this value
-    long            mForceNs;       // if overrun detected,
-                                    // force the write cycle to take this much time
-    long            mWarmupNsMin;   // warmup complete when write cycle is greater than or equal to
-                                    // this value
-    long            mWarmupNsMax;   // and less than or equal to this value
-    FastThreadDumpState* mDummyDumpState;
-    FastThreadDumpState* mDumpState;
-    bool            mIgnoreNextOverrun;     // used to ignore initial overrun and first after an
-                                            // underrun
-#ifdef FAST_THREAD_STATISTICS
-    struct timespec mOldLoad;       // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
-    bool            mOldLoadValid;  // whether oldLoad is valid
-    uint32_t        mBounds;
-    bool            mFull;          // whether we have collected at least mSamplingN samples
-#ifdef CPU_FREQUENCY_STATISTICS
-    ThreadCpuUsage  mTcu;           // for reading the current CPU clock frequency in kHz
-#endif
-#endif
-    unsigned        mColdGen;       // last observed mColdGen
-    bool            mIsWarm;        // true means ready to mix,
-                                    // false means wait for warmup before mixing
-    struct timespec   mMeasuredWarmupTs;  // how long did it take for warmup to complete
-    uint32_t          mWarmupCycles;  // counter of number of loop cycles during warmup phase
-    uint32_t          mWarmupConsecutiveInRangeCycles;    // number of consecutive cycles in range
-    const sp<NBLog::Writer> mDummyNBLogWriter{new NBLog::Writer()};
-    status_t          mTimestampStatus;
-
-    FastThreadState::Command mCommand;
-    bool            mAttemptedWrite;
-
-    char            mCycleMs[16];   // cycle_ms + suffix
-    char            mLoadUs[16];    // load_us + suffix
-
-};  // class FastThread
-
-}  // namespace android
-
-#endif  // ANDROID_AUDIO_FAST_THREAD_H
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 33983d7..78da621 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -116,8 +116,8 @@
             status_t    attachAuxEffect(int EffectId);
             void        setAuxBuffer(int EffectId, int32_t *buffer);
             int32_t     *auxBuffer() const { return mAuxBuffer; }
-            void        setMainBuffer(effect_buffer_t *buffer) { mMainBuffer = buffer; }
-            effect_buffer_t *mainBuffer() const { return mMainBuffer; }
+            void        setMainBuffer(float *buffer) { mMainBuffer = buffer; }
+            float       *mainBuffer() const { return mMainBuffer; }
             int         auxEffectId() const { return mAuxEffectId; }
     virtual status_t    getTimestamp(AudioTimestamp& timestamp);
             void        signal();
@@ -131,7 +131,7 @@
 // implement FastMixerState::VolumeProvider interface
     virtual gain_minifloat_packed_t getVolumeLR();
 
-    virtual status_t    setSyncEvent(const sp<SyncEvent>& event);
+            status_t    setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
 
     virtual bool        isFastTrack() const { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
 
@@ -283,7 +283,7 @@
 
     bool                mResetDone;
     const audio_stream_type_t mStreamType;
-    effect_buffer_t     *mMainBuffer;
+    float     *mMainBuffer;
 
     int32_t             *mAuxBuffer;
     int                 mAuxEffectId;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index f0a5f76..d91a210 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -58,7 +58,7 @@
             void        appendDumpHeader(String8& result);
             void        appendDump(String8& result, bool active);
 
-            void        handleSyncStartEvent(const sp<SyncEvent>& event);
+            void        handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event);
             void        clearSyncStartEvent();
 
             void        updateTrackFrameInfo(int64_t trackFramesReleased,
@@ -107,12 +107,10 @@
 
             // sync event triggering actual audio capture. Frames read before this event will
             // be dropped and therefore not read by the application.
-            sp<SyncEvent>                       mSyncStartEvent;
+            sp<audioflinger::SyncEvent>        mSyncStartEvent;
 
-            // number of captured frames to drop after the start sync event has been received.
-            // when < 0, maximum frames to drop before starting capture even if sync event is
-            // not received
-            ssize_t                             mFramesToDrop;
+            audioflinger::SynchronizedRecordState
+                    mSynchronizedRecordState{mSampleRate}; // sampleRate defined in base
 
             // used by resampler to find source frames
             ResamplerBufferProvider            *mResamplerBufferProvider;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 02d058f..8c09477 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -74,8 +74,6 @@
 #include <media/audiohal/StreamHalInterface.h>
 
 #include "AudioFlinger.h"
-#include "FastMixer.h"
-#include "FastCapture.h"
 #include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
 
@@ -89,10 +87,10 @@
 #include <cpustats/ThreadCpuUsage.h>
 #endif
 
-#include "AutoPark.h"
+#include <fastpath/AutoPark.h>
 
 #include <pthread.h>
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
 
 // ----------------------------------------------------------------------------
 
@@ -1404,15 +1402,6 @@
 
     switch (mType) {
     case MIXER: {
-#ifndef MULTICHANNEL_EFFECT_CHAIN
-        // Reject any effect on mixer multichannel sinks.
-        // TODO: fix both format and multichannel issues with effects.
-        if (mChannelCount != FCC_2) {
-            ALOGW("%s: effect %s for multichannel(%d) on MIXER thread %s",
-                    __func__, desc->name, mChannelCount, mThreadName);
-            return BAD_VALUE;
-        }
-#endif
         audio_output_flags_t flags = mOutput->flags;
         if (hasFastMixer() || (flags & AUDIO_OUTPUT_FLAG_FAST)) {
             if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
@@ -1465,15 +1454,6 @@
                 __func__, desc->name, mThreadName);
         return BAD_VALUE;
     case DUPLICATING:
-#ifndef MULTICHANNEL_EFFECT_CHAIN
-        // Reject any effect on mixer multichannel sinks.
-        // TODO: fix both format and multichannel issues with effects.
-        if (mChannelCount != FCC_2) {
-            ALOGW("%s: effect %s for multichannel(%d) on DUPLICATING thread %s",
-                    __func__, desc->name, mChannelCount, mThreadName);
-            return BAD_VALUE;
-        }
-#endif
         if (audio_is_global_session(sessionId)) {
             ALOGW("%s: global effect %s on DUPLICATING thread %s",
                     __func__, desc->name, mThreadName);
@@ -3124,7 +3104,7 @@
     free(mEffectBuffer);
     mEffectBuffer = NULL;
     if (mEffectBufferEnabled) {
-        mEffectBufferFormat = EFFECT_BUFFER_FORMAT;
+        mEffectBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
         mEffectBufferSize = mNormalFrameCount * mixerChannelCount
                 * audio_bytes_per_sample(mEffectBufferFormat);
         (void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
@@ -3278,7 +3258,7 @@
     return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
 }
 
-status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<audioflinger::SyncEvent>& event)
 {
     if (!isValidSyncEvent(event)) {
         return BAD_VALUE;
@@ -3297,7 +3277,8 @@
     return NAME_NOT_FOUND;
 }
 
-bool AudioFlinger::PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event) const
+bool AudioFlinger::PlaybackThread::isValidSyncEvent(
+        const sp<audioflinger::SyncEvent>& event) const
 {
     return event->type() == AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
 }
@@ -3517,7 +3498,7 @@
 {
     audio_session_t session = chain->sessionId();
     sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
-    effect_buffer_t *buffer = nullptr; // only used for non global sessions
+    float *buffer = nullptr; // only used for non global sessions
 
     if (mType == SPATIALIZER) {
         if (!audio_is_global_session(session)) {
@@ -3535,7 +3516,7 @@
             size_t numSamples = mNormalFrameCount
                     * (audio_channel_count_from_out_mask(channelMask) + mHapticChannelCount);
             status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
-                    numSamples * sizeof(effect_buffer_t),
+                    numSamples * sizeof(float),
                     &halInBuffer);
             if (result != OK) return result;
 
@@ -3545,11 +3526,8 @@
                     &halOutBuffer);
             if (result != OK) return result;
 
-#ifdef FLOAT_EFFECT_CHAIN
             buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
-#else
-            buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
-#endif
+
             ALOGV("addEffectChain_l() creating new input buffer %p session %d",
                     buffer, session);
         } else {
@@ -3577,7 +3555,7 @@
         halOutBuffer = halInBuffer;
         ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
         if (!audio_is_global_session(session)) {
-            buffer = halInBuffer ? reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData())
+            buffer = halInBuffer ? reinterpret_cast<float*>(halInBuffer->externalData())
                                  : buffer;
             // Only one effect chain can be present in direct output thread and it uses
             // the sink buffer as input
@@ -3586,14 +3564,11 @@
                         * (audio_channel_count_from_out_mask(mMixerChannelMask)
                                                              + mHapticChannelCount);
                 const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
-                        numSamples * sizeof(effect_buffer_t),
+                        numSamples * sizeof(float),
                         &halInBuffer);
                 if (allocateStatus != OK) return allocateStatus;
-#ifdef FLOAT_EFFECT_CHAIN
+
                 buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
-#else
-                buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
-#endif
                 ALOGV("addEffectChain_l() creating new input buffer %p session %d",
                         buffer, session);
             }
@@ -3677,7 +3652,7 @@
             for (size_t j = 0; j < mTracks.size(); ++j) {
                 sp<Track> track = mTracks[j];
                 if (session == track->sessionId()) {
-                    track->setMainBuffer(reinterpret_cast<effect_buffer_t*>(mSinkBuffer));
+                    track->setMainBuffer(reinterpret_cast<float*>(mSinkBuffer));
                     chain->decTrackCnt();
                 }
             }
@@ -3730,7 +3705,7 @@
 bool AudioFlinger::PlaybackThread::threadLoop()
 NO_THREAD_SAFETY_ANALYSIS  // manual locking of AudioFlinger
 {
-    tlNBLogWriter = mNBLogWriter.get();
+    aflog::setThreadWriter(mNBLogWriter.get());
 
     Vector< sp<Track> > tracksToRemove;
 
@@ -4082,12 +4057,12 @@
 
                         const size_t audioBufferSize = mNormalFrameCount
                             * audio_bytes_per_frame(hapticSessionChannelCount,
-                                                    EFFECT_BUFFER_FORMAT);
+                                                    AUDIO_FORMAT_PCM_FLOAT);
                         memcpy_by_audio_format(
                                 (uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
-                                EFFECT_BUFFER_FORMAT,
+                                AUDIO_FORMAT_PCM_FLOAT,
                                 (const uint8_t*)effectChains[i]->inBuffer() + audioBufferSize,
-                                EFFECT_BUFFER_FORMAT, mNormalFrameCount * mHapticChannelCount);
+                                AUDIO_FORMAT_PCM_FLOAT, mNormalFrameCount * mHapticChannelCount);
                     }
                 }
             }
@@ -4575,7 +4550,8 @@
     if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
         if (*volume != mLeftVolFloat) {
             result = mOutput->stream->setVolume(*volume, *volume);
-            ALOGE_IF(result != OK,
+            // HAL can return INVALID_OPERATION if operation is not supported.
+            ALOGE_IF(result != OK && result != INVALID_OPERATION,
                      "Error when setting output stream volume: %d", result);
             if (result == NO_ERROR) {
                 mLeftVolFloat = *volume;
@@ -5729,7 +5705,7 @@
                 mAudioMixer->setParameter(
                         trackId,
                         AudioMixer::TRACK,
-                        AudioMixer::MIXER_FORMAT, (void *)EFFECT_BUFFER_FORMAT);
+                        AudioMixer::MIXER_FORMAT, (void *)AUDIO_FORMAT_PCM_FLOAT);
                 mAudioMixer->setParameter(
                         trackId,
                         AudioMixer::TRACK,
@@ -6190,8 +6166,18 @@
 
     // Ensure volumeshaper state always advances even when muted.
     const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
-    const auto [shaperVolume, shaperActive] = track->getVolumeHandler()->getVolume(
-            proxy->framesReleased());
+
+    const size_t framesReleased = proxy->framesReleased();
+    const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+    const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
+
+    ALOGV("%s: Direct/Offload bufferConsumed:%zu  timestamp frames:%lld  time:%lld",
+            __func__, framesReleased, (long long)frames, (long long)time);
+
+    const int64_t volumeShaperFrames =
+            mMonotonicFrameCounter.updateAndGetMonotonicFrameCount(frames, time);
+    const auto [shaperVolume, shaperActive] =
+            track->getVolumeHandler()->getVolume(volumeShaperFrames);
     mVolumeShaperActive = shaperActive;
 
     if (mMasterMute || mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
@@ -6667,6 +6653,7 @@
     mFlushPending = false;
     mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
     mTimestamp.clear();
+    mMonotonicFrameCounter.onFlush();
 }
 
 int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
@@ -8210,7 +8197,11 @@
                     overrun = OVERRUN_FALSE;
                 }
 
-                if (activeTrack->mFramesToDrop == 0) {
+                // MediaSyncEvent handling: Synchronize AudioRecord to AudioTrack completion.
+                const ssize_t framesToDrop =
+                        activeTrack->mSynchronizedRecordState.updateRecordFrames(framesOut);
+                if (framesToDrop == 0) {
+                    // no sync event, process normally, otherwise ignore.
                     if (framesOut > 0) {
                         activeTrack->mSink.frameCount = framesOut;
                         // Sanitize before releasing if the track has no access to the source data
@@ -8220,28 +8211,7 @@
                         }
                         activeTrack->releaseBuffer(&activeTrack->mSink);
                     }
-                } else {
-                    // FIXME could do a partial drop of framesOut
-                    if (activeTrack->mFramesToDrop > 0) {
-                        activeTrack->mFramesToDrop -= (ssize_t)framesOut;
-                        if (activeTrack->mFramesToDrop <= 0) {
-                            activeTrack->clearSyncStartEvent();
-                        }
-                    } else {
-                        activeTrack->mFramesToDrop += framesOut;
-                        if (activeTrack->mFramesToDrop >= 0 || activeTrack->mSyncStartEvent == 0 ||
-                                activeTrack->mSyncStartEvent->isCancelled()) {
-                            ALOGW("Synced record %s, session %d, trigger session %d",
-                                  (activeTrack->mFramesToDrop >= 0) ? "timed out" : "cancelled",
-                                  activeTrack->sessionId(),
-                                  (activeTrack->mSyncStartEvent != 0) ?
-                                          activeTrack->mSyncStartEvent->triggerSession() :
-                                          AUDIO_SESSION_NONE);
-                            activeTrack->clearSyncStartEvent();
-                        }
-                    }
                 }
-
                 if (framesOut == 0) {
                     break;
                 }
@@ -8574,20 +8544,10 @@
     if (event == AudioSystem::SYNC_EVENT_NONE) {
         recordTrack->clearSyncStartEvent();
     } else if (event != AudioSystem::SYNC_EVENT_SAME) {
-        recordTrack->mSyncStartEvent = mAudioFlinger->createSyncEvent(event,
-                                       triggerSession,
-                                       recordTrack->sessionId(),
-                                       syncStartEventCallback,
-                                       recordTrack);
-        // Sync event can be cancelled by the trigger session if the track is not in a
-        // compatible state in which case we start record immediately
-        if (recordTrack->mSyncStartEvent->isCancelled()) {
-            recordTrack->clearSyncStartEvent();
-        } else {
-            // do not wait for the event for more than AudioSystem::kSyncRecordStartTimeOutMs
-            recordTrack->mFramesToDrop = -(ssize_t)
-                    ((AudioSystem::kSyncRecordStartTimeOutMs * recordTrack->mSampleRate) / 1000);
-        }
+        recordTrack->mSynchronizedRecordState.startRecording(
+                mAudioFlinger->createSyncEvent(
+                        event, triggerSession,
+                        recordTrack->sessionId(), syncStartEventCallback, recordTrack));
     }
 
     {
@@ -8669,9 +8629,9 @@
     }
 }
 
-void AudioFlinger::RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
+void AudioFlinger::RecordThread::syncStartEventCallback(const wp<audioflinger::SyncEvent>& event)
 {
-    sp<SyncEvent> strongEvent = event.promote();
+    sp<audioflinger::SyncEvent> strongEvent = event.promote();
 
     if (strongEvent != 0) {
         sp<RefBase> ptr = strongEvent->cookie().promote();
@@ -8710,12 +8670,14 @@
     return false;
 }
 
-bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event __unused) const
+bool AudioFlinger::RecordThread::isValidSyncEvent(
+        const sp<audioflinger::SyncEvent>& /* event */) const
 {
     return false;
 }
 
-status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event __unused)
+status_t AudioFlinger::RecordThread::setSyncEvent(
+        const sp<audioflinger::SyncEvent>& event __unused)
 {
 #if 0   // This branch is currently dead code, but is preserved in case it will be needed in future
     if (!isValidSyncEvent(event)) {
@@ -10248,12 +10210,13 @@
     // and because it can cause a recursive mutex lock on stop().
 }
 
-status_t AudioFlinger::MmapThread::setSyncEvent(const sp<SyncEvent>& event __unused)
+status_t AudioFlinger::MmapThread::setSyncEvent(const sp<audioflinger::SyncEvent>& /* event */)
 {
     return BAD_VALUE;
 }
 
-bool AudioFlinger::MmapThread::isValidSyncEvent(const sp<SyncEvent>& event __unused) const
+bool AudioFlinger::MmapThread::isValidSyncEvent(
+        const sp<audioflinger::SyncEvent>& /* event */) const
 {
     return false;
 }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 63ad4e6..45a4a95 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -516,8 +516,8 @@
                                                  audio_session_t sessionId,
                                                  bool threadLocked);
 
-                virtual status_t    setSyncEvent(const sp<SyncEvent>& event) = 0;
-                virtual bool        isValidSyncEvent(const sp<SyncEvent>& event) const = 0;
+                virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+                virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
 
                 // Return a reference to a per-thread heap which can be used to allocate IMemory
                 // objects that will be read-only to client processes, read/write to mediaserver,
@@ -1002,8 +1002,8 @@
                 status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
                 // Consider also removing and passing an explicit mMainBuffer initialization
                 // parameter to AF::PlaybackThread::Track::Track().
-                effect_buffer_t *sinkBuffer() const {
-                    return reinterpret_cast<effect_buffer_t *>(mSinkBuffer); };
+                float *sinkBuffer() const {
+                    return reinterpret_cast<float *>(mSinkBuffer); };
 
     virtual     void detachAuxEffect_l(int effectId);
                 status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
@@ -1019,8 +1019,8 @@
                 virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId);
 
 
-                virtual status_t setSyncEvent(const sp<SyncEvent>& event);
-                virtual bool     isValidSyncEvent(const sp<SyncEvent>& event) const;
+                status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+                bool     isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
 
                 // called with AudioFlinger lock held
                         bool     invalidateTracks_l(audio_stream_type_t streamType);
@@ -1581,6 +1581,8 @@
     virtual     void        onAddNewTrack_l();
 
     const       audio_offload_info_t mOffloadInfo;
+
+    audioflinger::MonotonicFrameCounter mMonotonicFrameCounter;  // for VolumeShaper
     bool mVolumeShaperActive = false;
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
@@ -1919,10 +1921,10 @@
             // FIXME replace by Set [and implement Bag/Multiset for other uses].
             KeyedVector<audio_session_t, bool> sessionIds() const;
 
-    virtual status_t setSyncEvent(const sp<SyncEvent>& event);
-    virtual bool     isValidSyncEvent(const sp<SyncEvent>& event) const;
+            status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+            bool     isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
 
-    static void syncStartEventCallback(const wp<SyncEvent>& event);
+    static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
 
     virtual size_t      frameCount() const { return mFrameCount; }
             bool        hasFastCapture() const { return mFastCapture != 0; }
@@ -2125,8 +2127,8 @@
                                 // Note: using mActiveTracks as no mTracks here.
                                 return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
                             }
-    virtual     status_t    setSyncEvent(const sp<SyncEvent>& event);
-    virtual     bool        isValidSyncEvent(const sp<SyncEvent>& event) const;
+    virtual     status_t    setSyncEvent(const sp<audioflinger::SyncEvent>& event);
+    virtual     bool        isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const;
 
     virtual     void        checkSilentMode_l() {}
     virtual     void        processVolume_l() {}
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 42f7b47..6c42dc8 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -67,7 +67,7 @@
                                 pid_t creatorPid,
                                 uid_t uid,
                                 bool isOut,
-                                alloc_type alloc = ALLOC_CBLK,
+                                const alloc_type alloc = ALLOC_CBLK,
                                 track_type type = TYPE_DEFAULT,
                                 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
                                 std::string metricsId = {});
@@ -84,7 +84,7 @@
             pid_t       creatorPid() const { return mCreatorPid; }
 
             audio_port_handle_t portId() const { return mPortId; }
-    virtual status_t    setSyncEvent(const sp<SyncEvent>& event);
+    virtual status_t    setSyncEvent(const sp<audioflinger::SyncEvent>& event);
 
             sp<IMemory> getBuffers() const { return mBufferMemory; }
             void*       buffer() const { return mBuffer; }
@@ -350,6 +350,7 @@
                                     // this could be a track type if needed later
 
     const wp<ThreadBase> mThread;
+    const alloc_type     mAllocType;
     /*const*/ sp<Client> mClient;   // see explanation at ~TrackBase() why not const
     sp<IMemory>         mCblkMemory;
     audio_track_cblk_t* mCblk;
@@ -373,7 +374,7 @@
 
     const audio_session_t mSessionId;
     uid_t               mUid;
-    Vector < sp<SyncEvent> >mSyncEvents;
+    std::list<sp<audioflinger::SyncEvent>> mSyncEvents;
     const bool          mIsOut;
     sp<ServerProxy>     mServerProxy;
     const int           mId;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 123d5a9..5444c60 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -90,12 +90,13 @@
             pid_t creatorPid,
             uid_t clientUid,
             bool isOut,
-            alloc_type alloc,
+            const alloc_type alloc,
             track_type type,
             audio_port_handle_t portId,
             std::string metricsId)
     :   RefBase(),
         mThread(thread),
+        mAllocType(alloc),
         mClient(client),
         mCblk(NULL),
         // mBuffer, mBufferSize
@@ -276,6 +277,10 @@
         // relying on the automatic clear() at end of scope.
         mClient.clear();
     }
+    if (mAllocType == ALLOC_LOCAL) {
+        free(mBuffer);
+        mBuffer = nullptr;
+    }
     // flush the binder command buffer
     IPCThreadState::self()->flushCommands();
 }
@@ -297,9 +302,10 @@
     mServerProxy->releaseBuffer(&buf);
 }
 
-status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(
+        const sp<audioflinger::SyncEvent>& event)
 {
-    mSyncEvents.add(event);
+    mSyncEvents.emplace_back(event);
     return NO_ERROR;
 }
 
@@ -1361,25 +1367,7 @@
         const sp<VolumeShaper::Configuration>& configuration,
         const sp<VolumeShaper::Operation>& operation)
 {
-    sp<VolumeShaper::Configuration> newConfiguration;
-
-    if (isOffloadedOrDirect()) {
-        const VolumeShaper::Configuration::OptionFlag optionFlag
-            = configuration->getOptionFlags();
-        if ((optionFlag & VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME) == 0) {
-            ALOGW("%s(%d): %s tracks do not support frame counted VolumeShaper,"
-                    " using clock time instead",
-                    __func__, mId,
-                    isOffloaded() ? "Offload" : "Direct");
-            newConfiguration = new VolumeShaper::Configuration(*configuration);
-            newConfiguration->setOptionFlags(
-                VolumeShaper::Configuration::OptionFlag(optionFlag
-                        | VolumeShaper::Configuration::OPTION_FLAG_CLOCK_TIME));
-        }
-    }
-
-    VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(
-            (newConfiguration.get() != nullptr ? newConfiguration : configuration), operation);
+    VolumeShaper::Status status = mVolumeHandler->applyVolumeShaper(configuration, operation);
 
     if (isOffloadedOrDirect()) {
         // Signal thread to fetch new volume.
@@ -1625,12 +1613,13 @@
 
 void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
 {
-    for (size_t i = 0; i < mSyncEvents.size();) {
-        if (mSyncEvents[i]->type() == type) {
-            mSyncEvents[i]->trigger();
-            mSyncEvents.removeAt(i);
+    for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
+        if ((*it)->type() == type) {
+            ALOGV("%s: triggering SyncEvent type %d", __func__, type);
+            (*it)->trigger();
+            it = mSyncEvents.erase(it);
         } else {
-            ++i;
+            ++it;
         }
     }
 }
@@ -1662,7 +1651,8 @@
     return vlr;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp<SyncEvent>& event)
+status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+        const sp<audioflinger::SyncEvent>& event)
 {
     if (isTerminated() || mState == PAUSED ||
             ((framesReady() == 0) && ((mSharedBuffer != 0) ||
@@ -1876,6 +1866,8 @@
         }
     }
 
+    ALOGV("%s: trackFramesReleased:%lld  sinkFramesWritten:%lld  setDrained: %d",
+        __func__, (long long)trackFramesReleased, (long long)sinkFramesWritten, drained);
     mAudioTrackServerProxy->setDrained(drained);
     // Set correction for flushed frames that are not accounted for in released.
     local.mFlushed = mAudioTrackServerProxy->framesFlushed();
@@ -2410,7 +2402,6 @@
                   type, portId,
                   std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD) + std::to_string(portId)),
         mOverflow(false),
-        mFramesToDrop(0),
         mResamplerBufferProvider(NULL), // initialize in case of early constructor exit
         mRecordBufferConverter(NULL),
         mFlags(flags),
@@ -2612,27 +2603,24 @@
     result.append("\n");
 }
 
-void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(const sp<SyncEvent>& event)
+// This is invoked by SyncEvent callback.
+void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(
+        const sp<audioflinger::SyncEvent>& event)
 {
-    if (event == mSyncStartEvent) {
-        ssize_t framesToDrop = 0;
-        sp<ThreadBase> threadBase = mThread.promote();
-        if (threadBase != 0) {
-            // TODO: use actual buffer filling status instead of 2 buffers when info is available
-            // from audio HAL
-            framesToDrop = threadBase->mFrameCount * 2;
-        }
-        mFramesToDrop = framesToDrop;
+    size_t framesToDrop = 0;
+    sp<ThreadBase> threadBase = mThread.promote();
+    if (threadBase != 0) {
+        // TODO: use actual buffer filling status instead of 2 buffers when info is available
+        // from audio HAL
+        framesToDrop = threadBase->mFrameCount * 2;
     }
+
+    mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
 }
 
 void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
 {
-    if (mSyncStartEvent != 0) {
-        mSyncStartEvent->cancel();
-        mSyncStartEvent.clear();
-    }
-    mFramesToDrop = 0;
+    mSynchronizedRecordState.clear();
 }
 
 void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
diff --git a/services/audioflinger/TypedLogger.cpp b/services/audioflinger/TypedLogger.cpp
deleted file mode 100644
index 57c206b..0000000
--- a/services/audioflinger/TypedLogger.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *
- * Copyright 2017, 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 "AudioFlinger"
-//#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <pthread.h>
-#include "TypedLogger.h"
-
-namespace android {
-thread_local NBLog::Writer *tlNBLogWriter;
-}
diff --git a/services/audioflinger/afutils/Android.bp b/services/audioflinger/afutils/Android.bp
new file mode 100644
index 0000000..5eac519
--- /dev/null
+++ b/services/audioflinger/afutils/Android.bp
@@ -0,0 +1,137 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+audioflinger_utils_tidy_errors = [
+    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+    // For many categories, the checks are too many to specify individually.
+    // Feel free to disable as needed - as warnings are generally ignored,
+    // we treat warnings as errors.
+    "android-*",
+    "bugprone-*",
+    "cert-*",
+    "clang-analyzer-security*",
+    "google-*",
+    "misc-*",
+    //"modernize-*",  // explicitly list the modernize as they can be subjective.
+    "modernize-avoid-bind",
+    //"modernize-avoid-c-arrays", // std::array<> can be verbose
+    "modernize-concat-nested-namespaces",
+    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+    "modernize-deprecated-ios-base-aliases",
+    "modernize-loop-convert",
+    "modernize-make-shared",
+    "modernize-make-unique",
+    // "modernize-pass-by-value",
+    "modernize-raw-string-literal",
+    "modernize-redundant-void-arg",
+    "modernize-replace-auto-ptr",
+    "modernize-replace-random-shuffle",
+    "modernize-return-braced-init-list",
+    "modernize-shrink-to-fit",
+    "modernize-unary-static-assert",
+    // "modernize-use-auto",  // found in MediaMetricsService.h, debatable - auto can obscure type
+    "modernize-use-bool-literals",
+    "modernize-use-default-member-init",
+    "modernize-use-emplace",
+    "modernize-use-equals-default",
+    "modernize-use-equals-delete",
+    // "modernize-use-nodiscard",
+    "modernize-use-noexcept",
+    "modernize-use-nullptr",
+    "modernize-use-override",
+    //"modernize-use-trailing-return-type", // not necessarily more readable
+    "modernize-use-transparent-functors",
+    "modernize-use-uncaught-exceptions",
+    "modernize-use-using",
+    "performance-*",
+
+    // Remove some pedantic stylistic requirements.
+    "-google-readability-casting", // C++ casts not always necessary and may be verbose
+    "-google-readability-todo",    // do not require TODO(info)
+
+    "-bugprone-unhandled-self-assignment",
+    "-bugprone-suspicious-string-compare",
+    "-cert-oop54-cpp", // found in TransactionLog.h
+    "-bugprone-narrowing-conversions", // b/182410845
+
+    // TODO(b/275642749) Reenable these warnings
+    "-misc-non-private-member-variables-in-classes",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+    name: "audioflinger_utils_flags_defaults",
+    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+    // https://clang.llvm.org/docs/DiagnosticsReference.html
+    cflags: [
+        "-Wall",
+        "-Wdeprecated",
+        "-Werror",
+        "-Werror=implicit-fallthrough",
+        "-Werror=sometimes-uninitialized",
+        "-Werror=conditional-uninitialized",
+        "-Wextra",
+
+        // suppress some warning chatter.
+        "-Wno-deprecated-copy-with-dtor",
+        "-Wno-deprecated-copy-with-user-provided-dtor",
+
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wstrict-aliasing",
+        "-fstrict-aliasing",
+        "-Wthread-safety",
+        //"-Wthread-safety-negative", // experimental - looks broken in R.
+        "-Wunreachable-code",
+        "-Wunreachable-code-break",
+        "-Wunreachable-code-return",
+        "-Wunused",
+        "-Wused-but-marked-unused",
+        "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+    ],
+    // https://clang.llvm.org/extra/clang-tidy/
+    tidy: true,
+    tidy_checks: audioflinger_utils_tidy_errors,
+    tidy_checks_as_errors: audioflinger_utils_tidy_errors,
+    tidy_flags: [
+      "-format-style=file",
+    ],
+}
+
+cc_library {
+    name: "libaudioflinger_utils",
+
+    defaults: [
+        "audioflinger_utils_flags_defaults",
+    ],
+
+    srcs: [
+        "AudioWatchdog.cpp",
+        "BufLog.cpp",
+        "NBAIO_Tee.cpp",
+        "TypedLogger.cpp",
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "libbase",
+        "liblog",
+        "libnbaio",
+        "libnblog",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libsndfile",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/audioflinger",  // for configuration
+    ],
+}
diff --git a/services/audioflinger/AudioWatchdog.cpp b/services/audioflinger/afutils/AudioWatchdog.cpp
similarity index 85%
rename from services/audioflinger/AudioWatchdog.cpp
rename to services/audioflinger/afutils/AudioWatchdog.cpp
index 877e776..48a07a5 100644
--- a/services/audioflinger/AudioWatchdog.cpp
+++ b/services/audioflinger/afutils/AudioWatchdog.cpp
@@ -38,12 +38,12 @@
             mUnderruns, mLogs, buf);
 }
 
-bool AudioWatchdog::threadLoop()
+bool AudioWatchdog::threadLoop() NO_THREAD_SAFETY_ANALYSIS // unique_lock
 {
     {
-        AutoMutex _l(mMyLock);
+        std::unique_lock _l(mLock);
         if (mPaused) {
-            mMyCond.wait(mMyLock);
+            mCond.wait(_l);
             // ignore previous timestamp after resume()
             mOldTsValid = false;
             // force an immediate log on first underrun after resume()
@@ -65,7 +65,7 @@
         return true;
     }
     time_t sec = newTs.tv_sec - mOldTs.tv_sec;
-    long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
+    auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
     if (nsec < 0) {
         --sec;
         nsec += 1000000000;
@@ -81,7 +81,8 @@
         }
     }
     mLogTs.tv_sec += sec;
-    if ((mLogTs.tv_nsec += nsec) >= 1000000000) {
+    mLogTs.tv_nsec += nsec;
+    if (mLogTs.tv_nsec >= 1000000000) {
         mLogTs.tv_sec++;
         mLogTs.tv_nsec -= 1000000000;
     }
@@ -89,7 +90,7 @@
         mDump->mUnderruns = ++mUnderruns;
         if (mLogTs.tv_sec >= MIN_TIME_BETWEEN_LOGS_SEC) {
             mDump->mLogs = ++mLogs;
-            mDump->mMostRecent = time(NULL);
+            mDump->mMostRecent = time(nullptr /* tloc */);
             ALOGW("Insufficient CPU for load: expected=%.1f actual=%.1f ms; underruns=%u logs=%u",
                 mPeriodNs * 1e-6, cycleNs * 1e-6, mUnderruns, mLogs);
             mLogTs.tv_sec = 0;
@@ -99,7 +100,7 @@
     struct timespec req;
     req.tv_sec = 0;
     req.tv_nsec = mPeriodNs;
-    rc = nanosleep(&req, NULL);
+    rc = nanosleep(&req, nullptr /* remaining */);
     if (!((rc == 0) || (rc == -1 && errno == EINTR))) {
         pause();
         return false;
@@ -116,22 +117,23 @@
 
 void AudioWatchdog::pause()
 {
-    AutoMutex _l(mMyLock);
+    const std::lock_guard _l(mLock);
     mPaused = true;
 }
 
 void AudioWatchdog::resume()
 {
-    AutoMutex _l(mMyLock);
+    const std::lock_guard _l(mLock);
     if (mPaused) {
         mPaused = false;
-        mMyCond.signal();
+        mCond.notify_one();
     }
 }
 
 void AudioWatchdog::setDump(AudioWatchdogDump *dump)
 {
-    mDump = dump != NULL ? dump : &mDummyDump;
+    const std::lock_guard _l(mLock);
+    mDump = dump != nullptr ? dump : &mDummyDump;
 }
 
 }   // namespace android
diff --git a/services/audioflinger/afutils/AudioWatchdog.h b/services/audioflinger/afutils/AudioWatchdog.h
new file mode 100644
index 0000000..1f5dad4
--- /dev/null
+++ b/services/audioflinger/afutils/AudioWatchdog.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+// The watchdog thread runs periodically.  It has two functions:
+//   (a) verify that adequate CPU time is available, and log
+//       as soon as possible when there appears to be a CPU shortage
+//   (b) monitor the other threads [not yet implemented]
+
+#pragma once
+
+#include <mutex>
+#include <time.h>
+#include <utils/Thread.h>
+
+namespace android {
+
+// Keeps a cache of AudioWatchdog statistics that can be logged by dumpsys.
+// The usual caveats about atomicity of information apply.
+struct AudioWatchdogDump {
+    uint32_t mUnderruns = 0;    // total number of underruns
+    uint32_t mLogs = 0;         // total number of log messages
+    time_t   mMostRecent = 0;   // time of most recent log
+    void     dump(int fd);  // should only be called on a stable copy, not the original
+};
+
+class AudioWatchdog : public Thread {
+
+public:
+    explicit AudioWatchdog(unsigned periodMs = 50) : Thread(false /*canCallJava*/),
+            mPeriodNs(periodMs * 1000000), mMaxCycleNs(mPeriodNs * 2)
+        {
+            // force an immediate log on first underrun
+            mLogTs.tv_sec = MIN_TIME_BETWEEN_LOGS_SEC;
+            mLogTs.tv_nsec = 0;
+        }
+
+     // Do not call Thread::requestExitAndWait() without first calling requestExit().
+    // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough.
+    void            requestExit() override;
+
+    // FIXME merge API and implementation with AudioTrackThread
+    void            pause();   // suspend thread from execution at next loop boundary
+    void            resume();  // allow thread to execute, if not requested to exit
+
+    // Where to store the dump, or NULL to not update
+    void            setDump(AudioWatchdogDump* dump);
+
+private:
+    bool            threadLoop() override;
+
+    static constexpr int32_t MIN_TIME_BETWEEN_LOGS_SEC = 60;
+    const uint32_t  mPeriodNs;       // nominal period
+    const uint32_t  mMaxCycleNs;     // maximum allowed time of one cycle before declaring underrun
+
+    mutable std::mutex mLock;      // Thread::mLock is private
+    std::condition_variable mCond; // Thread::mThreadExitedCondition is private
+    bool            mPaused GUARDED_BY(mLock) = false; // whether thread is currently paused
+    bool            mOldTsValid GUARDED_BY(mLock) = false;  // whether mOldTs is valid
+    struct timespec mOldTs GUARDED_BY(mLock);          // monotonic time when threadLoop last ran
+    struct timespec mLogTs GUARDED_BY(mLock);          // time since last log (ctor init).
+    uint32_t        mUnderruns GUARDED_BY(mLock) = 0;  // total number of underruns
+    uint32_t        mLogs GUARDED_BY(mLock) = 0;       // total number of logs
+
+    // where to store the dump, always non-NULL
+    AudioWatchdogDump*  mDump GUARDED_BY(mLock) = &mDummyDump;
+    AudioWatchdogDump   mDummyDump; // default area for dump in case setDump() is not called
+};
+
+}   // namespace android
+
diff --git a/services/audioflinger/BufLog.cpp b/services/audioflinger/afutils/BufLog.cpp
similarity index 77%
rename from services/audioflinger/BufLog.cpp
rename to services/audioflinger/afutils/BufLog.cpp
index 5f6aca0..508022f 100644
--- a/services/audioflinger/BufLog.cpp
+++ b/services/audioflinger/afutils/BufLog.cpp
@@ -28,12 +28,14 @@
 
 #define MIN(a, b) ((a) < (b) ? (a) : (b))
 
+namespace android {
+
 // ------------------------------
 // BufLogSingleton
 // ------------------------------
 pthread_once_t onceControl = PTHREAD_ONCE_INIT;
 
-BufLog *BufLogSingleton::mInstance = NULL;
+BufLog *BufLogSingleton::mInstance = nullptr;
 
 void BufLogSingleton::initOnce() {
     mInstance = new BufLog();
@@ -49,55 +51,39 @@
 }
 
 bool BufLogSingleton::instanceExists() {
-    return mInstance != NULL;
+    return mInstance != nullptr;
 }
 
 // ------------------------------
 // BufLog
 // ------------------------------
 
-BufLog::BufLog() {
-    memset(mStreams, 0, sizeof(mStreams));
-}
-
 BufLog::~BufLog() {
-    android::Mutex::Autolock autoLock(mLock);
-
-    for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
-        BufLogStream *pBLStream = mStreams[id];
-        if (pBLStream != NULL) {
-            delete pBLStream ;
-            mStreams[id] = NULL;
-        }
-    }
+    reset();
 }
 
 size_t BufLog::write(int streamid, const char *tag, int format, int channels,
         int samplingRate, size_t maxBytes, const void *buf, size_t size) {
-    unsigned int id = streamid % BUFLOG_MAXSTREAMS;
-    android::Mutex::Autolock autoLock(mLock);
+    const unsigned int id = streamid % BUFLOG_MAXSTREAMS;
+    const std::lock_guard autoLock(mLock);
 
     BufLogStream *pBLStream = mStreams[id];
 
-    if (pBLStream == NULL) {
+    if (pBLStream == nullptr) {
         pBLStream = mStreams[id] = new BufLogStream(id, tag, format, channels,
                 samplingRate, maxBytes);
-        ALOG_ASSERT(pBLStream != NULL, "BufLogStream Failed to be created");
     }
 
     return pBLStream->write(buf, size);
 }
 
 void BufLog::reset() {
-    android::Mutex::Autolock autoLock(mLock);
-    ALOGV("Resetting all BufLogs");
+    const std::lock_guard autoLock(mLock);
     int count = 0;
-
-    for (unsigned int id = 0; id < BUFLOG_MAXSTREAMS; id++) {
-        BufLogStream *pBLStream = mStreams[id];
-        if (pBLStream != NULL) {
+    for (auto &pBLStream : mStreams) {
+        if (pBLStream != nullptr) {
             delete pBLStream;
-            mStreams[id] = NULL;
+            pBLStream = nullptr;
             count++;
         }
     }
@@ -115,9 +101,7 @@
         unsigned int samplingRate,
         size_t maxBytes = 0) : mId(id), mFormat(format), mChannels(channels),
                 mSamplingRate(samplingRate), mMaxBytes(maxBytes) {
-    mByteCount = 0;
-    mPaused = false;
-    if (tag != NULL) {
+    if (tag != nullptr) {
         (void)audio_utils_strlcpy(mTag, tag);
     } else {
         mTag[0] = 0;
@@ -129,7 +113,7 @@
     //timestamp
     char timeStr[16];   //size 16: format %Y%m%d%H%M%S 14 chars + string null terminator
     struct timeval tv;
-    gettimeofday(&tv, NULL);
+    gettimeofday(&tv, nullptr);
     struct tm tm;
     localtime_r(&tv.tv_sec, &tm);
     strftime(timeStr, sizeof(timeStr), "%Y%m%d%H%M%S", &tm);
@@ -139,7 +123,7 @@
     ALOGV("data output: %s", logPath);
 
     mFile = fopen(logPath, "wb");
-    if (mFile != NULL) {
+    if (mFile != nullptr) {
         ALOGV("Success creating file at: %p", mFile);
     } else {
         ALOGE("Error: could not create file BufLogStream %s", strerror(errno));
@@ -148,24 +132,24 @@
 
 void BufLogStream::closeStream_l() {
     ALOGV("Closing BufLogStream id:%d tag:%s", mId, mTag);
-    if (mFile != NULL) {
+    if (mFile != nullptr) {
         fclose(mFile);
-        mFile = NULL;
+        mFile = nullptr;
     }
 }
 
 BufLogStream::~BufLogStream() {
     ALOGV("Destroying BufLogStream id:%d tag:%s", mId, mTag);
-    android::Mutex::Autolock autoLock(mLock);
+    const std::lock_guard autoLock(mLock);
     closeStream_l();
 }
 
 size_t BufLogStream::write(const void *buf, size_t size) {
 
     size_t bytes = 0;
-    if (!mPaused && mFile != NULL) {
-        if (size > 0 && buf != NULL) {
-            android::Mutex::Autolock autoLock(mLock);
+    if (!mPaused && mFile != nullptr) {
+        if (size > 0 && buf != nullptr) {
+            const std::lock_guard autoLock(mLock);
             if (mMaxBytes > 0) {
                 size = MIN(size, mMaxBytes - mByteCount);
             }
@@ -185,12 +169,14 @@
 }
 
 bool BufLogStream::setPause(bool pause) {
-    bool old = mPaused;
+    const bool old = mPaused;
     mPaused = pause;
     return old;
 }
 
 void BufLogStream::finalize() {
-    android::Mutex::Autolock autoLock(mLock);
+    const std::lock_guard autoLock(mLock);
     closeStream_l();
 }
+
+} // namespace android
diff --git a/services/audioflinger/BufLog.h b/services/audioflinger/afutils/BufLog.h
similarity index 92%
rename from services/audioflinger/BufLog.h
rename to services/audioflinger/afutils/BufLog.h
index 1b402f4..a58d073 100644
--- a/services/audioflinger/BufLog.h
+++ b/services/audioflinger/afutils/BufLog.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_BUFLOG_H
-#define ANDROID_AUDIO_BUFLOG_H
+#pragma once
 
 /*
  * BUFLOG creates up to BUFLOG_MAXSTREAMS simultaneous streams [0:15] of audio buffer data
@@ -99,17 +98,18 @@
     BufLogSingleton::instance()->reset(); } } while (0)
 #endif
 
-
+#include <mutex>
 #include <stdint.h>
 #include <stdio.h>
 #include <sys/types.h>
-#include <utils/Mutex.h>
 
 //BufLog configuration
 #define BUFLOGSTREAM_MAX_TAGSIZE    32
 #define BUFLOG_BASE_PATH            "/data/misc/audioserver"
 #define BUFLOG_MAX_PATH_SIZE        300
 
+namespace android {
+
 class BufLogStream {
 public:
     BufLogStream(unsigned int id,
@@ -135,26 +135,24 @@
     void            finalize();
 
 private:
-    bool                mPaused;
     const unsigned int  mId;
-    char                mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1];
     const unsigned int  mFormat;
     const unsigned int  mChannels;
     const unsigned int  mSamplingRate;
     const size_t        mMaxBytes;
-    size_t              mByteCount;
-    FILE                *mFile;
-    mutable android::Mutex mLock;
+    char                mTag[BUFLOGSTREAM_MAX_TAGSIZE + 1]; // const, set in ctor.
+
+    mutable std::mutex  mLock;
+    bool                mPaused = false;
+    size_t              mByteCount = 0;
+    FILE                *mFile; // set in ctor
 
     void            closeStream_l();
 };
 
-
 class BufLog {
 public:
-    BufLog();
     ~BufLog();
-    BufLog(BufLog const&) {};
 
     //  streamid:      int [0:BUFLOG_MAXSTREAMS-1]   buffer id.
     //                  If a buffer doesn't exist, it is created the first time is referenced
@@ -181,9 +179,9 @@
     void            reset();
 
 protected:
-    static const unsigned int BUFLOG_MAXSTREAMS = 16;
-    BufLogStream    *mStreams[BUFLOG_MAXSTREAMS];
-    mutable android::Mutex mLock;
+    static constexpr size_t BUFLOG_MAXSTREAMS = 16;
+    mutable std::mutex mLock;
+    BufLogStream *mStreams[BUFLOG_MAXSTREAMS]{};
 };
 
 class BufLogSingleton {
@@ -196,4 +194,4 @@
     static BufLog   *mInstance;
 };
 
-#endif //ANDROID_AUDIO_BUFLOG_H
+} // namespace android
diff --git a/services/audioflinger/NBAIO_Tee.cpp b/services/audioflinger/afutils/NBAIO_Tee.cpp
similarity index 90%
rename from services/audioflinger/NBAIO_Tee.cpp
rename to services/audioflinger/afutils/NBAIO_Tee.cpp
index 53083d5..49057ce 100644
--- a/services/audioflinger/NBAIO_Tee.cpp
+++ b/services/audioflinger/afutils/NBAIO_Tee.cpp
@@ -91,8 +91,8 @@
 
     /** returns filename of created audio file, else empty string on failure. */
     std::string create(
-            std::function<ssize_t /* frames_read */
-                        (void * /* buffer */, size_t /* size_in_frames */)> reader,
+            const std::function<ssize_t /* frames_read */
+                        (void * /* buffer */, size_t /* size_in_frames */)>& reader,
             uint32_t sampleRate,
             uint32_t channelCount,
             audio_format_t format,
@@ -109,8 +109,8 @@
 
     /** creates an audio file from a reader functor passed in. */
     status_t createInternal(
-            std::function<ssize_t /* frames_read */
-                        (void * /* buffer */, size_t /* size_in_frames */)> reader,
+            const std::function<ssize_t /* frames_read */
+                        (void * /* buffer */, size_t /* size_in_frames */)>& reader,
             uint32_t sampleRate,
             uint32_t channelCount,
             audio_format_t format,
@@ -123,7 +123,7 @@
     std::string generateFilename(const std::string &suffix) const {
         char fileTime[sizeof("YYYYmmdd_HHMMSS_\0")];
         struct timeval tv;
-        gettimeofday(&tv, NULL);
+        gettimeofday(&tv, nullptr /* struct timezone */);
         struct tm tm;
         localtime_r(&tv.tv_sec, &tm);
         LOG_ALWAYS_FATAL_IF(strftime(fileTime, sizeof(fileTime), "%Y%m%d_%H%M%S_", &tm) == 0,
@@ -159,30 +159,29 @@
     // yet another ThreadPool implementation.
     class ThreadPool {
     public:
-        ThreadPool(size_t size)
+        explicit ThreadPool(size_t size)
             : mThreadPoolSize(size)
         { }
 
         /** launches task "name" with associated function "func".
             if the threadpool is exhausted, it will launch on calling function */
-        status_t launch(const std::string &name, std::function<status_t()> func);
+        status_t launch(const std::string &name, const std::function<status_t()>& func);
 
     private:
+        const size_t mThreadPoolSize;
         std::mutex mLock;
         std::list<std::pair<
-                std::string, std::future<status_t>>> mFutures; // GUARDED_BY(mLock)
-
-        const size_t mThreadPoolSize;
+                std::string, std::future<status_t>>> mFutures; // GUARDED_BY(mLock);
     } mThreadPool;
 
-    const std::string mPrefix;
-    std::mutex mLock;
-    std::string mDirectory;         // GUARDED_BY(mLock)
-    std::deque<std::string> mFiles; // GUARDED_BY(mLock)  sorted list of files by creation time
-
     static constexpr size_t FRAMES_PER_READ = 1024;
     static constexpr size_t MAX_FILES_READ = 1024;
     static constexpr size_t MAX_FILES_KEEP = 32;
+
+    const std::string mPrefix;
+    std::mutex mLock;
+    std::string mDirectory;         // GUARDED_BY(mLock);
+    std::deque<std::string> mFiles; // GUARDED_BY(mLock); // sorted list of files by creation time
 };
 
 /* static */
@@ -200,7 +199,7 @@
 
     const NBAIO_Format format = source->format();
     bool firstRead = true;
-    std::string filename = audioFileHandler.create(
+    const std::string filename = audioFileHandler.create(
             // this functor must not hold references to stack
             [firstRead, sinkSource] (void *buffer, size_t frames) mutable {
                     auto &source = sinkSource.second;
@@ -230,14 +229,16 @@
         Pipe *pipe = new Pipe(frames, format);
         size_t numCounterOffers = 0;
         const NBAIO_Format offers[1] = {format};
-        ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+        ssize_t index = pipe->negotiate(
+                offers, 1 /* numOffers */, nullptr /* counterOffers */, numCounterOffers);
         if (index != 0) {
             ALOGW("pipe failure to negotiate: %zd", index);
             goto exit;
         }
         PipeReader *pipeReader = new PipeReader(*pipe);
         numCounterOffers = 0;
-        index = pipeReader->negotiate(offers, 1, NULL, numCounterOffers);
+        index = pipeReader->negotiate(
+                offers, 1 /* numOffers */, nullptr /* counterOffers */, numCounterOffers);
         if (index != 0) {
             ALOGW("pipeReader failure to negotiate: %zd", index);
             goto exit;
@@ -251,14 +252,14 @@
 }
 
 std::string AudioFileHandler::create(
-        std::function<ssize_t /* frames_read */
-                    (void * /* buffer */, size_t /* size_in_frames */)> reader,
+        const std::function<ssize_t /* frames_read */
+                    (void * /* buffer */, size_t /* size_in_frames */)>& reader,
         uint32_t sampleRate,
         uint32_t channelCount,
         audio_format_t format,
         const std::string &suffix)
 {
-    const std::string filename = generateFilename(suffix);
+    std::string filename = generateFilename(suffix);
 
     if (mThreadPool.launch(std::string("create ") + filename,
             [=]() { return createInternal(reader, sampleRate, channelCount, format, filename); })
@@ -312,7 +313,7 @@
     std::sort(files.begin() + toRemove, files.end());
 
     {
-        std::lock_guard<std::mutex> _l(mLock);
+        const std::lock_guard<std::mutex> _l(mLock);
 
         mDirectory = directory;
         mFiles = std::move(files);
@@ -330,13 +331,13 @@
     std::vector<std::string> filesToRemove;
     std::string dir;
     {
-        std::lock_guard<std::mutex> _l(mLock);
+        const std::lock_guard<std::mutex> _l(mLock);
 
         if (!isDirectoryValid(mDirectory)) return NO_INIT;
 
         dir = mDirectory;
         if (mFiles.size() > MAX_FILES_KEEP) {
-            size_t toRemove = mFiles.size() - MAX_FILES_KEEP;
+            const size_t toRemove = mFiles.size() - MAX_FILES_KEEP;
 
             // use move and erase to efficiently transfer std::string
             std::move(mFiles.begin(),
@@ -346,7 +347,7 @@
         }
     }
 
-    std::string dirp = dir + "/";
+    const std::string dirp = dir + "/";
     // remove files outside of lock for better concurrency.
     for (const auto &file : filesToRemove) {
         (void)unlink((dirp + file).c_str());
@@ -360,14 +361,14 @@
 }
 
 status_t AudioFileHandler::ThreadPool::launch(
-        const std::string &name, std::function<status_t()> func)
+        const std::string &name, const std::function<status_t()>& func)
 {
     if (mThreadPoolSize > 1) {
-        std::lock_guard<std::mutex> _l(mLock);
+        const std::lock_guard<std::mutex> _l(mLock);
         if (mFutures.size() >= mThreadPoolSize) {
             for (auto it = mFutures.begin(); it != mFutures.end();) {
                 const std::string &filename = it->first;
-                std::future<status_t> &future = it->second;
+                const std::future<status_t> &future = it->second;
                 if (!future.valid() ||
                         future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) {
                     ALOGV("%s: future %s ready", __func__, filename.c_str());
@@ -389,8 +390,8 @@
 }
 
 status_t AudioFileHandler::createInternal(
-        std::function<ssize_t /* frames_read */
-                    (void * /* buffer */, size_t /* size_in_frames */)> reader,
+        const std::function<ssize_t /* frames_read */
+                    (void * /* buffer */, size_t /* size_in_frames */)>& reader,
         uint32_t sampleRate,
         uint32_t channelCount,
         audio_format_t format,
@@ -429,9 +430,9 @@
     }
 
     std::string directory;
-    status_t status = clean(&directory);
+    const status_t status = clean(&directory);
     if (status != NO_ERROR) return status;
-    std::string dirPrefix = directory + "/";
+    const std::string dirPrefix = directory + "/";
 
     const std::string path = dirPrefix + filename;
 
@@ -503,7 +504,7 @@
 
     // Success: add our name to managed files.
     {
-        std::lock_guard<std::mutex> _l(mLock);
+        const std::lock_guard<std::mutex> _l(mLock);
         // weak synchronization - only update mFiles if the directory hasn't changed.
         if (mDirectory == directory) {
             mFiles.emplace_back(filename);  // add to the end to preserve sort.
diff --git a/services/audioflinger/NBAIO_Tee.h b/services/audioflinger/afutils/NBAIO_Tee.h
similarity index 96%
rename from services/audioflinger/NBAIO_Tee.h
rename to services/audioflinger/afutils/NBAIO_Tee.h
index fed8cc8..17b6175 100644
--- a/services/audioflinger/NBAIO_Tee.h
+++ b/services/audioflinger/afutils/NBAIO_Tee.h
@@ -15,8 +15,8 @@
  */
 
 // Enabled with TEE_SINK in Configuration.h
-#ifndef ANDROID_NBAIO_TEE_H
-#define ANDROID_NBAIO_TEE_H
+
+#pragma once
 
 #ifdef TEE_SINK
 
@@ -216,7 +216,7 @@
             // Note: as mentioned in NBAIO_Tee::set(), don't call set() while write() is
             // ongoing.
             if (enabled) {
-                std::lock_guard<std::mutex> _l(mLock);
+                const std::lock_guard<std::mutex> _l(mLock);
                 mFlags = flags;
                 mFormat = format; // could get this from the Sink.
                 mFrames = frames;
@@ -228,7 +228,7 @@
         }
 
         void setId(const std::string &id) {
-            std::lock_guard<std::mutex> _l(mLock);
+            const std::lock_guard<std::mutex> _l(mLock);
             mId = id;
         }
 
@@ -237,7 +237,7 @@
             std::string suffix;
             NBAIO_SinkSource sinkSource;
             {
-                std::lock_guard<std::mutex> _l(mLock);
+                const std::lock_guard<std::mutex> _l(mLock);
                 suffix = mId + reason;
                 sinkSource = mSinkSource;
             }
@@ -281,13 +281,13 @@
     class RunningTees {
     public:
         void add(const std::shared_ptr<NBAIO_TeeImpl> &tee) {
-            std::lock_guard<std::mutex> _l(mLock);
+            const std::lock_guard<std::mutex> _l(mLock);
             ALOGW_IF(!mTees.emplace(tee).second,
                     "%s: %p already exists in mTees", __func__, tee.get());
         }
 
         void remove(const std::shared_ptr<NBAIO_TeeImpl> &tee) {
-            std::lock_guard<std::mutex> _l(mLock);
+            const std::lock_guard<std::mutex> _l(mLock);
             ALOGW_IF(mTees.erase(tee) != 1,
                     "%s: %p doesn't exist in mTees", __func__, tee.get());
         }
@@ -295,7 +295,7 @@
         void dump(int fd, const std::string &reason) {
             std::vector<std::shared_ptr<NBAIO_TeeImpl>> tees; // safe snapshot of tees
             {
-                std::lock_guard<std::mutex> _l(mLock);
+                const std::lock_guard<std::mutex> _l(mLock);
                 tees.insert(tees.end(), mTees.begin(), mTees.end());
             }
             for (const auto &tee : tees) {
@@ -323,4 +323,3 @@
 } // namespace android
 
 #endif // TEE_SINK
-#endif // !ANDROID_NBAIO_TEE_H
diff --git a/services/audioflinger/afutils/TypedLogger.cpp b/services/audioflinger/afutils/TypedLogger.cpp
new file mode 100644
index 0000000..7c546a5
--- /dev/null
+++ b/services/audioflinger/afutils/TypedLogger.cpp
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2017, 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 "AudioFlinger"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <pthread.h>
+#include "TypedLogger.h"
+
+namespace android::aflog {
+
+// External linkage access of thread local storage outside of this shared library
+// causes orphaned memory allocations.  This occurs in the implementation of
+// __emutls_get_address(), see b/284657986.
+//
+// We only expose a thread local storage getter and setter here, not the
+// actual thread local variable.
+
+namespace {
+thread_local NBLog::Writer *tlNBLogWriter;
+} // namespace
+
+NBLog::Writer *getThreadWriter() {
+    return tlNBLogWriter;
+}
+
+void setThreadWriter(NBLog::Writer *writer) {
+    tlNBLogWriter = writer;
+}
+
+} // namespace android::aflog
diff --git a/services/audioflinger/TypedLogger.h b/services/audioflinger/afutils/TypedLogger.h
similarity index 78%
rename from services/audioflinger/TypedLogger.h
rename to services/audioflinger/afutils/TypedLogger.h
index feb71e3..8c2d239 100644
--- a/services/audioflinger/TypedLogger.h
+++ b/services/audioflinger/afutils/TypedLogger.h
@@ -15,8 +15,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_TYPED_LOGGER_H
-#define ANDROID_TYPED_LOGGER_H
+#pragma once
 
 // This is the client API for the typed logger.
 
@@ -85,56 +84,56 @@
 //      slower than nullptr check when logging is enabled at compile-time and disabled at runtime.
 
 // Write formatted entry to log
-#define LOGT(fmt, ...) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOGT(fmt, ...) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
                                 x->logFormat((fmt), hash(__FILE__, __LINE__), ##__VA_ARGS__); } \
                                 while (0)
 
 // Write histogram timestamp entry
-#define LOG_HIST_TS() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_HIST_TS() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->logEventHistTs(NBLog::EVENT_HISTOGRAM_ENTRY_TS, hash(__FILE__, __LINE__)); } while(0)
 
 // Record that audio was turned on/off
-#define LOG_AUDIO_STATE() do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_AUDIO_STATE() do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->logEventHistTs(NBLog::EVENT_AUDIO_STATE, hash(__FILE__, __LINE__)); } while(0)
 
 // Log the difference bewteen frames presented by HAL and frames written to HAL output sink,
 // divided by the sample rate. Parameter ms is of type double.
-#define LOG_LATENCY(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_LATENCY(ms) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_LATENCY>(ms); } while (0)
 
 // Record thread overrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_OVERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_OVERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_OVERRUN>(ns); } while (0)
 
 // Record thread info. This currently includes type, frameCount, and sampleRate.
 // Parameter type is thread_info_t as defined in NBLog.h.
-#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_INFO(info) do { NBLog::Writer *x = aflog::getThreadWriter(); \
         if (x != nullptr) x->log<NBLog::EVENT_THREAD_INFO>(info); } while (0)
 
-#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = tlNBLogWriter; \
+#define LOG_THREAD_PARAMS(params) do {NBLog::Writer *x = aflog::getThreadWriter(); \
         if (x != nullptr) x->log<NBLog::EVENT_THREAD_PARAMS>(params); } while (0)
 
 // Record thread underrun event nanosecond timestamp. Parameter ns is an int64_t.
-#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_UNDERRUN(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_UNDERRUN>(ns); } while (0)
 
 // Record thread warmup time in milliseconds. Parameter ms is of type double.
-#define LOG_WARMUP_TIME(ms) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WARMUP_TIME(ms) do { \
+        NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_WARMUP_TIME>(ms); } while (0)
 
 // Record a typed entry that represents a thread's work time in nanoseconds.
 // Parameter ns should be of type uint32_t.
-#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = tlNBLogWriter; if (x != nullptr) \
+#define LOG_WORK_TIME(ns) do { NBLog::Writer *x = aflog::getThreadWriter(); if (x != nullptr) \
         x->log<NBLog::EVENT_WORK_TIME>(ns); } while (0)
 
-namespace android {
-extern "C" {
+namespace android::aflog {
 // TODO consider adding a thread_local NBLog::Writer tlStubNBLogWriter and then
-// initialize below tlNBLogWriter to &tlStubNBLogWriter to remove the need to
+// initialize setThreadWriter() to &tlStubNBLogWriter to remove the need to
 // check for nullptr every time. Also reduces the need to add a new logging macro above
 // each time we want to log a new type.
-extern thread_local NBLog::Writer *tlNBLogWriter;
-}
-} // namespace android
 
-#endif // ANDROID_TYPED_LOGGER_H
+NBLog::Writer *getThreadWriter();
+void setThreadWriter(NBLog::Writer *writer);
+
+} // namespace android::aflog
diff --git a/services/audioflinger/fastpath/Android.bp b/services/audioflinger/fastpath/Android.bp
new file mode 100644
index 0000000..6c024e7
--- /dev/null
+++ b/services/audioflinger/fastpath/Android.bp
@@ -0,0 +1,152 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+fastpath_tidy_errors = [
+    // https://clang.llvm.org/extra/clang-tidy/checks/list.html
+    // For many categories, the checks are too many to specify individually.
+    // Feel free to disable as needed - as warnings are generally ignored,
+    // we treat warnings as errors.
+    "android-*",
+    "bugprone-*",
+    "cert-*",
+    "clang-analyzer-security*",
+    "google-*",
+    "misc-*",
+    //"modernize-*",  // explicitly list the modernize as they can be subjective.
+    "modernize-avoid-bind",
+    //"modernize-avoid-c-arrays", // std::array<> can be verbose
+    "modernize-concat-nested-namespaces",
+    //"modernize-deprecated-headers", // C headers still ok even if there is C++ equivalent.
+    "modernize-deprecated-ios-base-aliases",
+    "modernize-loop-convert",
+    "modernize-make-shared",
+    "modernize-make-unique",
+    // "modernize-pass-by-value",
+    "modernize-raw-string-literal",
+    "modernize-redundant-void-arg",
+    "modernize-replace-auto-ptr",
+    "modernize-replace-random-shuffle",
+    "modernize-return-braced-init-list",
+    "modernize-shrink-to-fit",
+    "modernize-unary-static-assert",
+    // "modernize-use-auto",  // found in MediaMetricsService.h, debatable - auto can obscure type
+    "modernize-use-bool-literals",
+    "modernize-use-default-member-init",
+    "modernize-use-emplace",
+    "modernize-use-equals-default",
+    "modernize-use-equals-delete",
+    // "modernize-use-nodiscard",
+    "modernize-use-noexcept",
+    "modernize-use-nullptr",
+    "modernize-use-override",
+    //"modernize-use-trailing-return-type", // not necessarily more readable
+    "modernize-use-transparent-functors",
+    "modernize-use-uncaught-exceptions",
+    "modernize-use-using",
+    "performance-*",
+
+    // Remove some pedantic stylistic requirements.
+    "-google-readability-casting", // C++ casts not always necessary and may be verbose
+    "-google-readability-todo",    // do not require TODO(info)
+
+    "-bugprone-unhandled-self-assignment",
+    "-bugprone-suspicious-string-compare",
+    "-cert-oop54-cpp", // found in TransactionLog.h
+    "-bugprone-narrowing-conversions", // b/182410845
+
+    // TODO(b/275642749) Reenable these warnings
+    "-misc-non-private-member-variables-in-classes",
+    "-performance-no-int-to-ptr",
+]
+
+// Eventually use common tidy defaults
+cc_defaults {
+    name: "fastpath_flags_defaults",
+    // https://clang.llvm.org/docs/UsersManual.html#command-line-options
+    // https://clang.llvm.org/docs/DiagnosticsReference.html
+    cflags: [
+        "-Wall",
+        "-Wdeprecated",
+        "-Werror",
+        "-Werror=implicit-fallthrough",
+        "-Werror=sometimes-uninitialized",
+        "-Werror=conditional-uninitialized",
+        "-Wextra",
+
+        // suppress some warning chatter.
+        "-Wno-deprecated-copy-with-dtor",
+        "-Wno-deprecated-copy-with-user-provided-dtor",
+
+        "-Wredundant-decls",
+        "-Wshadow",
+        "-Wstrict-aliasing",
+        "-fstrict-aliasing",
+        "-Wthread-safety",
+        //"-Wthread-safety-negative", // experimental - looks broken in R.
+        "-Wunreachable-code",
+        "-Wunreachable-code-break",
+        "-Wunreachable-code-return",
+        "-Wunused",
+        "-Wused-but-marked-unused",
+        "-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS",
+    ],
+    // https://clang.llvm.org/extra/clang-tidy/
+    tidy: true,
+    tidy_checks: fastpath_tidy_errors,
+    tidy_checks_as_errors: fastpath_tidy_errors,
+    tidy_flags: [
+      "-format-style=file",
+    ],
+}
+
+cc_library_shared {
+    name: "libaudioflinger_fastpath",
+
+    defaults: [
+        "fastpath_flags_defaults",
+    ],
+
+    srcs: [
+        "FastCapture.cpp",
+        "FastCaptureDumpState.cpp",
+        "FastCaptureState.cpp",
+        "FastMixer.cpp",
+        "FastMixerDumpState.cpp",
+        "FastMixerState.cpp",
+        "FastThread.cpp",
+        "FastThreadDumpState.cpp",
+        "FastThreadState.cpp",
+        "StateQueue.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/audioflinger", // for Configuration
+    ],
+
+    shared_libs: [
+        "libaudioflinger_utils", // NBAIO_Tee
+        "libaudioprocessing",
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+        "libnbaio",
+        "libnblog", // legacy NBLog that can be removed.
+        "libutils",
+    ],
+
+    header_libs: [
+        "libaudiohal_headers",
+        "libmedia_headers",
+    ],
+
+    sanitize: {
+        integer_overflow: true,
+    },
+
+}
diff --git a/services/audioflinger/AutoPark.h b/services/audioflinger/fastpath/AutoPark.h
similarity index 99%
rename from services/audioflinger/AutoPark.h
rename to services/audioflinger/fastpath/AutoPark.h
index 83f6b7d..6e68327 100644
--- a/services/audioflinger/AutoPark.h
+++ b/services/audioflinger/fastpath/AutoPark.h
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#pragma once
+
 namespace android {
 
 // T is FastMixer or FastCapture
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/fastpath/FastCapture.cpp
similarity index 85%
rename from services/audioflinger/FastCapture.cpp
rename to services/audioflinger/fastpath/FastCapture.cpp
index 2963202..288036d 100644
--- a/services/audioflinger/FastCapture.cpp
+++ b/services/audioflinger/fastpath/FastCapture.cpp
@@ -30,24 +30,16 @@
 
 namespace android {
 
-/*static*/ const FastCaptureState FastCapture::sInitial;
+/*static*/ const FastCaptureState FastCapture::sInitial{};
 
-FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us"),
-    mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0),
-    mReadBuffer(NULL), mReadBufferState(-1), mFormat(Format_Invalid), mSampleRate(0),
-    // mDummyDumpState
-    mTotalNativeFramesRead(0)
+FastCapture::FastCapture() : FastThread("cycleC_ms", "loadC_us")
 {
+    // base class initialization
     mPrevious = &sInitial;
     mCurrent = &sInitial;
-
     mDummyDumpState = &mDummyFastCaptureDumpState;
 }
 
-FastCapture::~FastCapture()
-{
-}
-
 FastCaptureStateQueue* FastCapture::sq()
 {
     return &mSQ;
@@ -95,11 +87,11 @@
     bool eitherChanged = false;
 
     // check for change in input HAL configuration
-    NBAIO_Format previousFormat = mFormat;
+    const NBAIO_Format previousFormat = mFormat;
     if (current->mInputSourceGen != mInputSourceGen) {
         mInputSource = current->mInputSource;
         mInputSourceGen = current->mInputSourceGen;
-        if (mInputSource == NULL) {
+        if (mInputSource == nullptr) {
             mFormat = Format_Invalid;
             mSampleRate = 0;
         } else {
@@ -122,19 +114,19 @@
     }
 
     // input source and pipe sink must be compatible
-    if (eitherChanged && mInputSource != NULL && mPipeSink != NULL) {
+    if (eitherChanged && mInputSource != nullptr && mPipeSink != nullptr) {
         ALOG_ASSERT(Format_isEqual(mFormat, mPipeSink->format()));
     }
 
     if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
         // FIXME to avoid priority inversion, don't free here
         free(mReadBuffer);
-        mReadBuffer = NULL;
+        mReadBuffer = nullptr;
         if (frameCount > 0 && mSampleRate > 0) {
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal capture thread allocate for
             //       us to avoid blocking here and to prevent possible priority inversion
-            size_t bufferSize = frameCount * Format_frameSize(mFormat);
+            const size_t bufferSize = frameCount * Format_frameSize(mFormat);
             (void)posix_memalign(&mReadBuffer, 32, bufferSize);
             memset(mReadBuffer, 0, bufferSize); // if posix_memalign fails, will segv here.
             mPeriodNs = (frameCount * 1000000000LL) / mSampleRate;      // 1.00
@@ -166,9 +158,9 @@
     AudioBufferProvider* fastPatchRecordBufferProvider = current->mFastPatchRecordBufferProvider;
     AudioBufferProvider::Buffer patchBuffer;
 
-    if (fastPatchRecordBufferProvider != 0) {
+    if (fastPatchRecordBufferProvider != nullptr) {
         patchBuffer.frameCount = ~0;
-        status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
+        const status_t status = fastPatchRecordBufferProvider->getNextBuffer(&patchBuffer);
         if (status != NO_ERROR) {
             frameCount = 0;
         } else if (patchBuffer.frameCount < frameCount) {
@@ -179,11 +171,11 @@
     }
 
     if ((command & FastCaptureState::READ) /*&& isWarm*/) {
-        ALOG_ASSERT(mInputSource != NULL);
-        ALOG_ASSERT(mReadBuffer != NULL);
+        ALOG_ASSERT(mInputSource != nullptr);
+        ALOG_ASSERT(mReadBuffer != nullptr);
         dumpState->mReadSequence++;
         ATRACE_BEGIN("read");
-        ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
+        const ssize_t framesRead = mInputSource->read(mReadBuffer, frameCount);
         ATRACE_END();
         dumpState->mReadSequence++;
         if (framesRead >= 0) {
@@ -201,8 +193,8 @@
     }
 
     if (command & FastCaptureState::WRITE) {
-        ALOG_ASSERT(mPipeSink != NULL);
-        ALOG_ASSERT(mReadBuffer != NULL);
+        ALOG_ASSERT(mPipeSink != nullptr);
+        ALOG_ASSERT(mReadBuffer != nullptr);
         if (mReadBufferState < 0) {
             memset(mReadBuffer, 0, frameCount * Format_frameSize(mFormat));
             mReadBufferState = frameCount;
@@ -211,23 +203,23 @@
             if (current->mSilenceCapture) {
                 memset(mReadBuffer, 0, mReadBufferState * Format_frameSize(mFormat));
             }
-            ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
+            const ssize_t framesWritten = mPipeSink->write(mReadBuffer, mReadBufferState);
             audio_track_cblk_t* cblk = current->mCblk;
-            if (fastPatchRecordBufferProvider != 0) {
+            if (fastPatchRecordBufferProvider != nullptr) {
                 // This indicates the fast track is a patch record, update the cblk by
                 // calling releaseBuffer().
                 memcpy_by_audio_format(patchBuffer.raw, current->mFastPatchRecordFormat,
                         mReadBuffer, mFormat.mFormat, framesWritten * mFormat.mChannelCount);
                 patchBuffer.frameCount = framesWritten;
                 fastPatchRecordBufferProvider->releaseBuffer(&patchBuffer);
-            } else if (cblk != NULL && framesWritten > 0) {
+            } else if (cblk != nullptr && framesWritten > 0) {
                 // FIXME This supports at most one fast capture client.
                 //       To handle multiple clients this could be converted to an array,
                 //       or with a lot more work the control block could be shared by all clients.
-                int32_t rear = cblk->u.mStreaming.mRear;
+                const int32_t rear = cblk->u.mStreaming.mRear;
                 android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
                 cblk->mServer += framesWritten;
-                int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+                const int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
                 if (!(old & CBLK_FUTEX_WAKE)) {
                     // client is never in server process, so don't use FUTEX_WAKE_PRIVATE
                     (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
diff --git a/services/audioflinger/fastpath/FastCapture.h b/services/audioflinger/fastpath/FastCapture.h
new file mode 100644
index 0000000..b565216
--- /dev/null
+++ b/services/audioflinger/fastpath/FastCapture.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "FastThread.h"
+#include "StateQueue.h"
+#include "FastCaptureState.h"
+#include "FastCaptureDumpState.h"
+
+namespace android {
+
+using FastCaptureStateQueue = StateQueue<FastCaptureState>;
+
+class FastCapture : public FastThread {
+
+public:
+            FastCapture();
+
+            FastCaptureStateQueue*  sq();
+
+private:
+            FastCaptureStateQueue   mSQ;
+
+    // callouts
+    const FastThreadState *poll() override;
+    void setNBLogWriter(NBLog::Writer *logWriter) override;
+    void onIdle() override;
+    void onExit() override;
+    bool isSubClassCommand(FastThreadState::Command command) override;
+    void onStateChange() override;
+    void onWork() override;
+
+    static const FastCaptureState sInitial;
+
+    FastCaptureState    mPreIdle;   // copy of state before we went into idle
+    // FIXME by renaming, could pull up many of these to FastThread
+    NBAIO_Source*       mInputSource = nullptr;
+    int                 mInputSourceGen = 0;
+    NBAIO_Sink*         mPipeSink = nullptr;
+    int                 mPipeSinkGen = 0;
+    void*               mReadBuffer = nullptr;
+    ssize_t             mReadBufferState = -1;  // number of initialized frames in readBuffer,
+                                                // or -1 to clear
+    NBAIO_Format        mFormat = Format_Invalid;
+    unsigned            mSampleRate = 0;
+    FastCaptureDumpState mDummyFastCaptureDumpState;
+    uint32_t            mTotalNativeFramesRead = 0; // copied to dumpState->mFramesRead
+
+};  // class FastCapture
+
+}   // namespace android
diff --git a/services/audioflinger/FastCaptureDumpState.cpp b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
similarity index 82%
rename from services/audioflinger/FastCaptureDumpState.cpp
rename to services/audioflinger/fastpath/FastCaptureDumpState.cpp
index 243dfa5..fe7ea16 100644
--- a/services/audioflinger/FastCaptureDumpState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.cpp
@@ -24,24 +24,15 @@
 
 namespace android {
 
-FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
-    mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
-{
-}
-
-FastCaptureDumpState::~FastCaptureDumpState()
-{
-}
-
 void FastCaptureDumpState::dump(int fd) const
 {
     if (mCommand == FastCaptureState::INITIAL) {
         dprintf(fd, "  FastCapture not initialized\n");
         return;
     }
-    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+    const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
             (mMeasuredWarmupTs.tv_nsec / 1000000.0);
-    double periodSec = (double) mFrameCount / mSampleRate;
+    const double periodSec = (double) mFrameCount / mSampleRate;
     dprintf(fd, "  FastCapture command=%s readSequence=%u framesRead=%u\n"
                 "              readErrors=%u sampleRate=%u frameCount=%zu\n"
                 "              measuredWarmup=%.3g ms, warmupCycles=%u period=%.2f ms\n"
diff --git a/services/audioflinger/FastCaptureDumpState.h b/services/audioflinger/fastpath/FastCaptureDumpState.h
similarity index 67%
rename from services/audioflinger/FastCaptureDumpState.h
rename to services/audioflinger/fastpath/FastCaptureDumpState.h
index 34ce456..3dc8a9b 100644
--- a/services/audioflinger/FastCaptureDumpState.h
+++ b/services/audioflinger/fastpath/FastCaptureDumpState.h
@@ -14,30 +14,28 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+#pragma once
 
 #include <stdint.h>
+#include <type_traits>
 #include "Configuration.h"
 #include "FastThreadDumpState.h"
 
 namespace android {
 
 struct FastCaptureDumpState : FastThreadDumpState {
-    FastCaptureDumpState();
-    /*virtual*/ ~FastCaptureDumpState();
-
     void dump(int fd) const;    // should only be called on a stable copy, not the original
 
     // FIXME by renaming, could pull up many of these to FastThreadDumpState
-    uint32_t mReadSequence;     // incremented before and after each read()
-    uint32_t mFramesRead;       // total number of frames read successfully
-    uint32_t mReadErrors;       // total number of read() errors
-    uint32_t mSampleRate;
-    size_t   mFrameCount;
+    uint32_t mReadSequence = 0;  // incremented before and after each read()
+    uint32_t mFramesRead = 0;    // total number of frames read successfully
+    uint32_t mReadErrors = 0;    // total number of read() errors
+    uint32_t mSampleRate = 0;
+    size_t   mFrameCount = 0;
     bool     mSilenced = false; // capture is silenced
 };
 
-}  // namespace android
+// No virtuals
+static_assert(!std::is_polymorphic_v<FastCaptureDumpState>);
 
-#endif  // ANDROID_AUDIO_FAST_CAPTURE_DUMP_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/fastpath/FastCaptureState.cpp
similarity index 80%
rename from services/audioflinger/FastCaptureState.cpp
rename to services/audioflinger/fastpath/FastCaptureState.cpp
index 918ba9c..77c0c4c 100644
--- a/services/audioflinger/FastCaptureState.cpp
+++ b/services/audioflinger/fastpath/FastCaptureState.cpp
@@ -18,20 +18,11 @@
 
 namespace android {
 
-FastCaptureState::FastCaptureState() : FastThreadState(),
-    mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0), mFrameCount(0)
-{
-}
-
-FastCaptureState::~FastCaptureState()
-{
-}
-
 // static
 const char *FastCaptureState::commandToString(Command command)
 {
     const char *str = FastThreadState::commandToString(command);
-    if (str != NULL) {
+    if (str != nullptr) {
         return str;
     }
     switch (command) {
@@ -39,7 +30,7 @@
     case FastCaptureState::WRITE:       return "WRITE";
     case FastCaptureState::READ_WRITE:  return "READ_WRITE";
     }
-    LOG_ALWAYS_FATAL("%s", __func__);
+    LOG_ALWAYS_FATAL("%s: command %d invalid", __func__, (int) command);
 }
 
 }  // namespace android
diff --git a/services/audioflinger/FastCaptureState.h b/services/audioflinger/fastpath/FastCaptureState.h
similarity index 76%
rename from services/audioflinger/FastCaptureState.h
rename to services/audioflinger/fastpath/FastCaptureState.h
index f949275..0f4126e 100644
--- a/services/audioflinger/FastCaptureState.h
+++ b/services/audioflinger/fastpath/FastCaptureState.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_CAPTURE_STATE_H
-#define ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+#pragma once
 
+#include <type_traits>
 #include <media/nbaio/NBAIO.h>
 #include <media/AudioBufferProvider.h>
 #include "FastThreadState.h"
@@ -26,16 +26,14 @@
 
 // Represent a single state of the fast capture
 struct FastCaptureState : FastThreadState {
-                FastCaptureState();
-    /*virtual*/ ~FastCaptureState();
-
     // all pointer fields use raw pointers; objects are owned and ref-counted by RecordThread
-    NBAIO_Source*   mInputSource;       // HAL input device, must already be negotiated
+    NBAIO_Source*   mInputSource = nullptr; // HAL input device, must already be negotiated
     // FIXME by renaming, could pull up these fields to FastThreadState
-    int             mInputSourceGen;    // increment when mInputSource is assigned
-    NBAIO_Sink*     mPipeSink;          // after reading from input source, write to this pipe sink
-    int             mPipeSinkGen;       // increment when mPipeSink is assigned
-    size_t          mFrameCount;        // number of frames per fast capture buffer
+    int             mInputSourceGen = 0;    // increment when mInputSource is assigned
+    NBAIO_Sink*     mPipeSink = nullptr;    // after reading from input source,
+                                            // write to this pipe sink
+    int             mPipeSinkGen = 0;       // increment when mPipeSink is assigned
+    size_t          mFrameCount = 0;        // number of frames per fast capture buffer
     audio_track_cblk_t* mCblk;          // control block for the single fast client, or NULL
 
     audio_format_t  mFastPatchRecordFormat = AUDIO_FORMAT_INVALID;
@@ -55,6 +53,7 @@
     static const char *commandToString(Command command);
 };  // struct FastCaptureState
 
-}   // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastCaptureState>);
 
-#endif  // ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+}   // namespace android
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/fastpath/FastMixer.cpp
similarity index 93%
rename from services/audioflinger/FastMixer.cpp
rename to services/audioflinger/fastpath/FastMixer.cpp
index 61dd3f2..e0a15c1 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/fastpath/FastMixer.cpp
@@ -42,7 +42,7 @@
 #include <cutils/bitops.h>
 #include <media/AudioMixer.h>
 #include "FastMixer.h"
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
 
 namespace android {
 
@@ -61,48 +61,25 @@
     : FastThread("cycle_ms", "load_us"),
     // mFastTrackNames
     // mGenerations
-    mOutputSink(NULL),
-    mOutputSinkGen(0),
-    mMixer(NULL),
-    mSinkBuffer(NULL),
-    mSinkBufferSize(0),
-    mSinkChannelCount(FCC_2),
-    mMixerBuffer(NULL),
-    mMixerBufferSize(0),
-    mMixerBufferState(UNDEFINED),
-    mFormat(Format_Invalid),
-    mSampleRate(0),
-    mFastTracksGen(0),
-    mTotalNativeFramesWritten(0),
     // timestamp
-    mNativeFramesWrittenButNotPresented(0),   // the = 0 is to silence the compiler
-    mMasterMono(false),
     mThreadIoHandle(parentIoHandle)
 {
     // FIXME pass sInitial as parameter to base class constructor, and make it static local
     mPrevious = &sInitial;
     mCurrent = &sInitial;
-
     mDummyDumpState = &mDummyFastMixerDumpState;
+
     // TODO: Add channel mask to NBAIO_Format.
     // We assume that the channel mask must be a valid positional channel mask.
     mSinkChannelMask = getChannelMaskFromCount(mSinkChannelCount);
     mBalance.setChannelMask(mSinkChannelMask);
 
-    unsigned i;
-    for (i = 0; i < FastMixerState::sMaxFastTracks; ++i) {
-        mGenerations[i] = 0;
-    }
 #ifdef FAST_THREAD_STATISTICS
     mOldLoad.tv_sec = 0;
     mOldLoad.tv_nsec = 0;
 #endif
 }
 
-FastMixer::~FastMixer()
-{
-}
-
 FastMixerStateQueue* FastMixer::sq()
 {
     return &mSQ;
@@ -229,13 +206,13 @@
     unsigned previousTrackMask;
 
     // check for change in output HAL configuration
-    NBAIO_Format previousFormat = mFormat;
+    const NBAIO_Format previousFormat = mFormat;
     if (current->mOutputSinkGen != mOutputSinkGen) {
         mOutputSink = current->mOutputSink;
         mOutputSinkGen = current->mOutputSinkGen;
         mSinkChannelMask = current->mSinkChannelMask;
         mBalance.setChannelMask(mSinkChannelMask);
-        if (mOutputSink == NULL) {
+        if (mOutputSink == nullptr) {
             mFormat = Format_Invalid;
             mSampleRate = 0;
             mSinkChannelCount = 0;
@@ -259,11 +236,11 @@
     if ((!Format_isEqual(mFormat, previousFormat)) || (frameCount != previous->mFrameCount)) {
         // FIXME to avoid priority inversion, don't delete here
         delete mMixer;
-        mMixer = NULL;
+        mMixer = nullptr;
         free(mMixerBuffer);
-        mMixerBuffer = NULL;
+        mMixerBuffer = nullptr;
         free(mSinkBuffer);
-        mSinkBuffer = NULL;
+        mSinkBuffer = nullptr;
         if (frameCount > 0 && mSampleRate > 0) {
             // FIXME new may block for unbounded time at internal mutex of the heap
             //       implementation; it would be better to have normal mixer allocate for us
@@ -320,7 +297,7 @@
         // process removed tracks first to avoid running out of track names
         unsigned removedTracks = previousTrackMask & ~currentTrackMask;
         while (removedTracks != 0) {
-            int i = __builtin_ctz(removedTracks);
+            const int i = __builtin_ctz(removedTracks);
             removedTracks &= ~(1 << i);
             updateMixerTrack(i, REASON_REMOVE);
             // don't reset track dump state, since other side is ignoring it
@@ -329,7 +306,7 @@
         // now process added tracks
         unsigned addedTracks = currentTrackMask & ~previousTrackMask;
         while (addedTracks != 0) {
-            int i = __builtin_ctz(addedTracks);
+            const int i = __builtin_ctz(addedTracks);
             addedTracks &= ~(1 << i);
             updateMixerTrack(i, REASON_ADD);
         }
@@ -338,7 +315,7 @@
         // but may have a different buffer provider or volume provider
         unsigned modifiedTracks = currentTrackMask & previousTrackMask;
         while (modifiedTracks != 0) {
-            int i = __builtin_ctz(modifiedTracks);
+            const int i = __builtin_ctz(modifiedTracks);
             modifiedTracks &= ~(1 << i);
             updateMixerTrack(i, REASON_MODIFY);
         }
@@ -373,8 +350,8 @@
     const FastMixerState::Command command = mCommand;
     const size_t frameCount = current->mFrameCount;
 
-    if ((command & FastMixerState::MIX) && (mMixer != NULL) && mIsWarm) {
-        ALOG_ASSERT(mMixerBuffer != NULL);
+    if ((command & FastMixerState::MIX) && (mMixer != nullptr) && mIsWarm) {
+        ALOG_ASSERT(mMixerBuffer != nullptr);
 
         // AudioMixer::mState.enabledTracks is undefined if mState.hook == process__validate,
         // so we keep a side copy of enabledTracks
@@ -383,7 +360,7 @@
         // for each track, update volume and check for underrun
         unsigned currentTrackMask = current->mTrackMask;
         while (currentTrackMask != 0) {
-            int i = __builtin_ctz(currentTrackMask);
+            const int i = __builtin_ctz(currentTrackMask);
             currentTrackMask &= ~(1 << i);
             const FastTrack* fastTrack = &current->mFastTracks[i];
 
@@ -406,8 +383,8 @@
             fastTrack->mBufferProvider->onTimestamp(perTrackTimestamp);
 
             const int name = i;
-            if (fastTrack->mVolumeProvider != NULL) {
-                gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
+            if (fastTrack->mVolumeProvider != nullptr) {
+                const gain_minifloat_packed_t vlr = fastTrack->mVolumeProvider->getVolumeLR();
                 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
                 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
 
@@ -418,7 +395,7 @@
             // takes a tryLock, which can block
             // up to 1 ms.  If enough active tracks all blocked in sequence, this would result
             // in the overall fast mix cycle being delayed.  Should use a non-blocking FIFO.
-            size_t framesReady = fastTrack->mBufferProvider->framesReady();
+            const size_t framesReady = fastTrack->mBufferProvider->framesReady();
             if (ATRACE_ENABLED()) {
                 // I wish we had formatted trace names
                 char traceName[16];
@@ -464,7 +441,8 @@
         mMixerBufferState = UNDEFINED;
     }
     //bool didFullWrite = false;    // dumpsys could display a count of partial writes
-    if ((command & FastMixerState::WRITE) && (mOutputSink != NULL) && (mMixerBuffer != NULL)) {
+    if ((command & FastMixerState::WRITE)
+            && (mOutputSink != nullptr) && (mMixerBuffer != nullptr)) {
         if (mMixerBufferState == UNDEFINED) {
             memset(mMixerBuffer, 0, mMixerBufferSize);
             mMixerBufferState = ZEROED;
@@ -481,7 +459,7 @@
         mBalance.process((float *)mMixerBuffer, frameCount);
 
         // prepare the buffer used to write to sink
-        void *buffer = mSinkBuffer != NULL ? mSinkBuffer : mMixerBuffer;
+        void *buffer = mSinkBuffer != nullptr ? mSinkBuffer : mMixerBuffer;
         if (mFormat.mFormat != mMixerBufferFormat) { // sink format not the same as mixer format
             memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
                     frameCount * Format_channelCount(mFormat));
@@ -493,7 +471,7 @@
                     audio_bytes_per_sample(mFormat.mFormat),
                     frameCount * audio_bytes_per_frame(mAudioChannelCount, mFormat.mFormat));
         }
-        // if non-NULL, then duplicate write() to this non-blocking sink
+        // if non-nullptr, then duplicate write() to this non-blocking sink
 #ifdef TEE_SINK
         mTee.write(buffer, frameCount);
 #endif
@@ -501,7 +479,7 @@
         //       but this code should be modified to handle both non-blocking and blocking sinks
         dumpState->mWriteSequence++;
         ATRACE_BEGIN("write");
-        ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
+        const ssize_t framesWritten = mOutputSink->write(buffer, frameCount);
         ATRACE_END();
         dumpState->mWriteSequence++;
         if (framesWritten >= 0) {
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/fastpath/FastMixer.h
similarity index 71%
rename from services/audioflinger/FastMixer.h
rename to services/audioflinger/fastpath/FastMixer.h
index d71519f..48b94a3 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/fastpath/FastMixer.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_MIXER_H
-#define ANDROID_AUDIO_FAST_MIXER_H
+#pragma once
 
 #include <atomic>
 #include <audio_utils/Balance.h>
@@ -23,13 +22,13 @@
 #include "StateQueue.h"
 #include "FastMixerState.h"
 #include "FastMixerDumpState.h"
-#include "NBAIO_Tee.h"
+#include <afutils/NBAIO_Tee.h>
 
 namespace android {
 
 class AudioMixer;
 
-typedef StateQueue<FastMixerState> FastMixerStateQueue;
+using FastMixerStateQueue = StateQueue<FastMixerState>;
 
 class FastMixer : public FastThread {
 
@@ -37,7 +36,6 @@
     /** FastMixer constructor takes as param the parent MixerThread's io handle (id)
         for purposes of identification. */
     explicit FastMixer(audio_io_handle_t threadIoHandle);
-    virtual ~FastMixer();
 
             FastMixerStateQueue* sq();
 
@@ -51,13 +49,13 @@
             FastMixerStateQueue mSQ;
 
     // callouts
-    virtual const FastThreadState *poll();
-    virtual void setNBLogWriter(NBLog::Writer *logWriter);
-    virtual void onIdle();
-    virtual void onExit();
-    virtual bool isSubClassCommand(FastThreadState::Command command);
-    virtual void onStateChange();
-    virtual void onWork();
+    const FastThreadState *poll() override;
+    void setNBLogWriter(NBLog::Writer *logWriter) override;
+    void onIdle() override;
+    void onExit() override;
+    bool isSubClassCommand(FastThreadState::Command command) override;
+    void onStateChange() override;
+    void onWork() override;
 
     enum Reason {
         REASON_REMOVE,
@@ -71,39 +69,39 @@
     static const FastMixerState sInitial;
 
     FastMixerState  mPreIdle;   // copy of state before we went into idle
-    int             mGenerations[FastMixerState::kMaxFastTracks];
+    int             mGenerations[FastMixerState::kMaxFastTracks]{};
                                 // last observed mFastTracks[i].mGeneration
-    NBAIO_Sink*     mOutputSink;
-    int             mOutputSinkGen;
-    AudioMixer*     mMixer;
+    NBAIO_Sink*     mOutputSink = nullptr;
+    int             mOutputSinkGen = 0;
+    AudioMixer*     mMixer = nullptr;
 
     // mSinkBuffer audio format is stored in format.mFormat.
-    void*           mSinkBuffer;        // used for mixer output format translation
+    void*           mSinkBuffer = nullptr; // used for mixer output format translation
                                         // if sink format is different than mixer output.
-    size_t          mSinkBufferSize;
-    uint32_t        mSinkChannelCount;
+    size_t          mSinkBufferSize = 0;
+    uint32_t        mSinkChannelCount = FCC_2;
     audio_channel_mask_t mSinkChannelMask;
-    void*           mMixerBuffer;       // mixer output buffer.
-    size_t          mMixerBufferSize;
+    void*           mMixerBuffer = nullptr;       // mixer output buffer.
+    size_t          mMixerBufferSize = 0;
     static constexpr audio_format_t mMixerBufferFormat = AUDIO_FORMAT_PCM_FLOAT;
 
     uint32_t        mAudioChannelCount; // audio channel count, excludes haptic channels.
 
-    enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState;
-    NBAIO_Format    mFormat;
-    unsigned        mSampleRate;
-    int             mFastTracksGen;
+    enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState = UNDEFINED;
+    NBAIO_Format    mFormat{Format_Invalid};
+    unsigned        mSampleRate = 0;
+    int             mFastTracksGen = 0;
     FastMixerDumpState mDummyFastMixerDumpState;
-    int64_t         mTotalNativeFramesWritten;  // copied to dumpState->mFramesWritten
+    int64_t         mTotalNativeFramesWritten = 0;  // copied to dumpState->mFramesWritten
 
     // next 2 fields are valid only when timestampStatus == NO_ERROR
     ExtendedTimestamp mTimestamp;
-    int64_t         mNativeFramesWrittenButNotPresented;
+    int64_t         mNativeFramesWrittenButNotPresented = 0;
 
     audio_utils::Balance mBalance;
 
     // accessed without lock between multiple threads.
-    std::atomic_bool mMasterMono;
+    std::atomic_bool mMasterMono{};
     std::atomic<float> mMasterBalance{};
     std::atomic_int_fast64_t mBoottimeOffset;
 
@@ -115,5 +113,3 @@
 };  // class FastMixer
 
 }   // namespace android
-
-#endif  // ANDROID_AUDIO_FAST_MIXER_H
diff --git a/services/audioflinger/FastMixerDumpState.cpp b/services/audioflinger/fastpath/FastMixerDumpState.cpp
similarity index 90%
rename from services/audioflinger/FastMixerDumpState.cpp
rename to services/audioflinger/fastpath/FastMixerDumpState.cpp
index d041882..4f79dd6 100644
--- a/services/audioflinger/FastMixerDumpState.cpp
+++ b/services/audioflinger/fastpath/FastMixerDumpState.cpp
@@ -29,23 +29,11 @@
 
 namespace android {
 
-FastMixerDumpState::FastMixerDumpState() : FastThreadDumpState(),
-    mWriteSequence(0), mFramesWritten(0),
-    mNumTracks(0), mWriteErrors(0),
-    mSampleRate(0), mFrameCount(0),
-    mTrackMask(0)
-{
-}
-
-FastMixerDumpState::~FastMixerDumpState()
-{
-}
-
 // helper function called by qsort()
 static int compare_uint32_t(const void *pa, const void *pb)
 {
-    uint32_t a = *(const uint32_t *)pa;
-    uint32_t b = *(const uint32_t *)pb;
+    const uint32_t a = *(const uint32_t *)pa;
+    const uint32_t b = *(const uint32_t *)pb;
     if (a < b) {
         return -1;
     } else if (a > b) {
@@ -61,9 +49,9 @@
         dprintf(fd, "  FastMixer not initialized\n");
         return;
     }
-    double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
+    const double measuredWarmupMs = (mMeasuredWarmupTs.tv_sec * 1000.0) +
             (mMeasuredWarmupTs.tv_nsec / 1000000.0);
-    double mixPeriodSec = (double) mFrameCount / mSampleRate;
+    const double mixPeriodSec = (double) mFrameCount / mSampleRate;
     dprintf(fd, "  FastMixer command=%s writeSequence=%u framesWritten=%u\n"
                 "            numTracks=%u writeErrors=%u underruns=%u overruns=%u\n"
                 "            sampleRate=%u frameCount=%zu measuredWarmup=%.3g ms, warmupCycles=%u\n"
@@ -99,16 +87,16 @@
     // the mean account for 99.73% of the population.  So if we take each tail to be 1/1000 of the
     // sample set, we get 99.8% combined, or close to three standard deviations.
     static const uint32_t kTailDenominator = 1000;
-    uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : NULL;
+    uint32_t *tail = n >= kTailDenominator ? new uint32_t[n] : nullptr;
     // loop over all the samples
     for (uint32_t j = 0; j < n; ++j) {
-        size_t i = oldestClosed++ & (mSamplingN - 1);
-        uint32_t wallNs = mMonotonicNs[i];
-        if (tail != NULL) {
+        const size_t i = oldestClosed++ & (mSamplingN - 1);
+        const uint32_t wallNs = mMonotonicNs[i];
+        if (tail != nullptr) {
             tail[j] = wallNs;
         }
         wall.add(wallNs);
-        uint32_t sampleLoadNs = mLoadNs[i];
+        const uint32_t sampleLoadNs = mLoadNs[i];
         loadNs.add(sampleLoadNs);
 #ifdef CPU_FREQUENCY_STATISTICS
         uint32_t sampleCpukHz = mCpukHz[i];
@@ -146,10 +134,10 @@
                 "    mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
                 loadMHz.getMean(), loadMHz.getMin(), loadMHz.getMax(), loadMHz.getStdDev());
 #endif
-    if (tail != NULL) {
+    if (tail != nullptr) {
         qsort(tail, n, sizeof(uint32_t), compare_uint32_t);
         // assume same number of tail samples on each side, left and right
-        uint32_t count = n / kTailDenominator;
+        const uint32_t count = n / kTailDenominator;
         audio_utils::Statistics<double> left, right;
         for (uint32_t i = 0; i < count; ++i) {
             left.add(tail[i]);
@@ -175,7 +163,7 @@
             FastMixerState::sMaxFastTracks, trackMask);
     dprintf(fd, "  Index Active Full Partial Empty  Recent Ready    Written\n");
     for (uint32_t i = 0; i < FastMixerState::sMaxFastTracks; ++i, trackMask >>= 1) {
-        bool isActive = trackMask & 1;
+        const bool isActive = trackMask & 1;
         const FastTrackDump *ftDump = &mTracks[i];
         const FastTrackUnderruns& underruns = ftDump->mUnderruns;
         const char *mostRecent;
diff --git a/services/audioflinger/FastMixerDumpState.h b/services/audioflinger/fastpath/FastMixerDumpState.h
similarity index 76%
rename from services/audioflinger/FastMixerDumpState.h
rename to services/audioflinger/fastpath/FastMixerDumpState.h
index 294ef78..1b0e029 100644
--- a/services/audioflinger/FastMixerDumpState.h
+++ b/services/audioflinger/fastpath/FastMixerDumpState.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+#pragma once
 
 #include <stdint.h>
+#include <type_traits>
 #include <audio_utils/TimestampVerifier.h>
 #include "Configuration.h"
 #include "FastThreadDumpState.h"
@@ -54,33 +54,32 @@
 
 // Represents the dump state of a fast track
 struct FastTrackDump {
-    FastTrackDump() : mFramesReady(0) { }
-    /*virtual*/ ~FastTrackDump() { }
     FastTrackUnderruns  mUnderruns;
-    size_t              mFramesReady;        // most recent value only; no long-term statistics kept
+    size_t              mFramesReady = 0;    // most recent value only; no long-term statistics kept
     int64_t             mFramesWritten;      // last value from track
 };
 
-struct FastMixerDumpState : FastThreadDumpState {
-    FastMixerDumpState();
-    /*virtual*/ ~FastMixerDumpState();
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrackDump>);
 
+struct FastMixerDumpState : FastThreadDumpState {
     void dump(int fd) const;    // should only be called on a stable copy, not the original
 
-    double   mLatencyMs = 0.;   // measured latency, default of 0 if no valid timestamp read.
-    uint32_t mWriteSequence;    // incremented before and after each write()
-    uint32_t mFramesWritten;    // total number of frames written successfully
-    uint32_t mNumTracks;        // total number of active fast tracks
-    uint32_t mWriteErrors;      // total number of write() errors
-    uint32_t mSampleRate;
-    size_t   mFrameCount;
-    uint32_t mTrackMask;        // mask of active tracks
+    double   mLatencyMs = 0.;     // measured latency, default of 0 if no valid timestamp read.
+    uint32_t mWriteSequence = 0;  // incremented before and after each write()
+    uint32_t mFramesWritten = 0;  // total number of frames written successfully
+    uint32_t mNumTracks = 0;      // total number of active fast tracks
+    uint32_t mWriteErrors = 0;    // total number of write() errors
+    uint32_t mSampleRate = 0;
+    size_t   mFrameCount = 0;
+    uint32_t mTrackMask = 0;      // mask of active tracks
     FastTrackDump   mTracks[FastMixerState::kMaxFastTracks];
 
     // For timestamp statistics.
     TimestampVerifier<int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
 };
 
-}  // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerDumpState>);
 
-#endif  // ANDROID_AUDIO_FAST_MIXER_DUMP_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/FastMixerState.cpp b/services/audioflinger/fastpath/FastMixerState.cpp
similarity index 73%
rename from services/audioflinger/FastMixerState.cpp
rename to services/audioflinger/fastpath/FastMixerState.cpp
index b98842d..4fe2d86 100644
--- a/services/audioflinger/FastMixerState.cpp
+++ b/services/audioflinger/fastpath/FastMixerState.cpp
@@ -22,31 +22,14 @@
 
 namespace android {
 
-FastTrack::FastTrack() :
-    mBufferProvider(NULL), mVolumeProvider(NULL),
-    mChannelMask(AUDIO_CHANNEL_OUT_STEREO), mFormat(AUDIO_FORMAT_INVALID), mGeneration(0)
+FastMixerState::FastMixerState() : FastThreadState()
 {
-}
-
-FastTrack::~FastTrack()
-{
-}
-
-FastMixerState::FastMixerState() : FastThreadState(),
-    // mFastTracks
-    mFastTracksGen(0), mTrackMask(0), mOutputSink(NULL), mOutputSinkGen(0),
-    mFrameCount(0)
-{
-    int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
+    const int ok = pthread_once(&sMaxFastTracksOnce, sMaxFastTracksInit);
     if (ok != 0) {
         ALOGE("%s pthread_once failed: %d", __func__, ok);
     }
 }
 
-FastMixerState::~FastMixerState()
-{
-}
-
 // static
 unsigned FastMixerState::sMaxFastTracks = kDefaultFastTracks;
 
@@ -57,7 +40,7 @@
 const char *FastMixerState::commandToString(Command command)
 {
     const char *str = FastThreadState::commandToString(command);
-    if (str != NULL) {
+    if (str != nullptr) {
         return str;
     }
     switch (command) {
@@ -72,9 +55,9 @@
 void FastMixerState::sMaxFastTracksInit()
 {
     char value[PROPERTY_VALUE_MAX];
-    if (property_get("ro.audio.max_fast_tracks", value, NULL) > 0) {
+    if (property_get("ro.audio.max_fast_tracks", value, nullptr /* default_value */) > 0) {
         char *endptr;
-        unsigned long ul = strtoul(value, &endptr, 0);
+        const auto ul = strtoul(value, &endptr, 0);
         if (*endptr == '\0' && kMinFastTracks <= ul && ul <= kMaxFastTracks) {
             sMaxFastTracks = (unsigned) ul;
         }
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/fastpath/FastMixerState.h
similarity index 71%
rename from services/audioflinger/FastMixerState.h
rename to services/audioflinger/fastpath/FastMixerState.h
index ce3cc14..fdf3eaa 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/fastpath/FastMixerState.h
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_MIXER_STATE_H
-#define ANDROID_AUDIO_FAST_MIXER_STATE_H
+#pragma once
 
 #include <math.h>
+#include <type_traits>
 
 #include <audio_utils/minifloat.h>
 #include <system/audio.h>
@@ -38,28 +38,32 @@
     virtual gain_minifloat_packed_t getVolumeLR() = 0;
 protected:
     VolumeProvider() { }
-    virtual ~VolumeProvider() { }
+    virtual ~VolumeProvider() = default;
 };
 
 // Represents the state of a fast track
 struct FastTrack {
-    FastTrack();
-    /*virtual*/ ~FastTrack();
+    // must be nullptr if inactive, or non-nullptr if active
+    ExtendedAudioBufferProvider* mBufferProvider = nullptr;
 
-    ExtendedAudioBufferProvider* mBufferProvider; // must be NULL if inactive, or non-NULL if active
-    VolumeProvider*         mVolumeProvider; // optional; if NULL then full-scale
-    audio_channel_mask_t    mChannelMask;    // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
-    audio_format_t          mFormat;         // track format
-    int                     mGeneration;     // increment when any field is assigned
+    // optional: if nullptr then full-scale
+    VolumeProvider*         mVolumeProvider = nullptr;
+
+    // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
+    audio_channel_mask_t    mChannelMask = AUDIO_CHANNEL_OUT_STEREO;
+    audio_format_t          mFormat = AUDIO_FORMAT_INVALID;         // track format
+    int                     mGeneration = 0;     // increment when any field is assigned
     bool                    mHapticPlaybackEnabled = false; // haptic playback is enabled or not
     os::HapticScale         mHapticIntensity = os::HapticScale::MUTE; // intensity of haptic data
     float                   mHapticMaxAmplitude = NAN; // max amplitude allowed for haptic data
 };
 
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastTrack>);
+
 // Represents a single state of the fast mixer
 struct FastMixerState : FastThreadState {
                 FastMixerState();
-    /*virtual*/ ~FastMixerState();
 
     // These are the minimum, maximum, and default values for maximum number of fast tracks
     static const unsigned kMinFastTracks = 2;
@@ -71,11 +75,12 @@
 
     // all pointer fields use raw pointers; objects are owned and ref-counted by the normal mixer
     FastTrack   mFastTracks[kMaxFastTracks];
-    int         mFastTracksGen; // increment when any mFastTracks[i].mGeneration is incremented
-    unsigned    mTrackMask;     // bit i is set if and only if mFastTracks[i] is active
-    NBAIO_Sink* mOutputSink;    // HAL output device, must already be negotiated
-    int         mOutputSinkGen; // increment when mOutputSink is assigned
-    size_t      mFrameCount;    // number of frames per fast mix buffer
+    int         mFastTracksGen = 0; // increment when any
+                                    // mFastTracks[i].mGeneration is incremented
+    unsigned    mTrackMask = 0;     // bit i is set if and only if mFastTracks[i] is active
+    NBAIO_Sink* mOutputSink = nullptr; // HAL output device, must already be negotiated
+    int         mOutputSinkGen = 0; // increment when mOutputSink is assigned
+    size_t      mFrameCount = 0;    // number of frames per fast mix buffer
     audio_channel_mask_t mSinkChannelMask; // If not AUDIO_CHANNEL_NONE, specifies sink channel
                                            // mask when it cannot be directly calculated from
                                            // channel count
@@ -95,6 +100,7 @@
 
 };  // struct FastMixerState
 
-}   // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastMixerState>);
 
-#endif  // ANDROID_AUDIO_FAST_MIXER_STATE_H
+}   // namespace android
diff --git a/services/audioflinger/FastThread.cpp b/services/audioflinger/fastpath/FastThread.cpp
similarity index 87%
rename from services/audioflinger/FastThread.cpp
rename to services/audioflinger/fastpath/FastThread.cpp
index 47fe0b3..d054d71 100644
--- a/services/audioflinger/FastThread.cpp
+++ b/services/audioflinger/fastpath/FastThread.cpp
@@ -28,7 +28,7 @@
 #include <utils/Trace.h>
 #include "FastThread.h"
 #include "FastThreadDumpState.h"
-#include "TypedLogger.h"
+#include <afutils/TypedLogger.h>
 
 #define FAST_DEFAULT_NS    999999999L   // ~1 sec: default time to sleep
 #define FAST_HOT_IDLE_NS     1000000L   // 1 ms: time to sleep while hot idling
@@ -38,69 +38,28 @@
 
 namespace android {
 
-FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/),
-    // re-initialized to &sInitial by subclass constructor
-    mPrevious(NULL), mCurrent(NULL),
-    /* mOldTs({0, 0}), */
-    mOldTsValid(false),
-    mSleepNs(-1),
-    mPeriodNs(0),
-    mUnderrunNs(0),
-    mOverrunNs(0),
-    mForceNs(0),
-    mWarmupNsMin(0),
-    mWarmupNsMax(LONG_MAX),
-    // re-initialized to &mDummySubclassDumpState by subclass constructor
-    mDummyDumpState(NULL),
-    mDumpState(NULL),
-    mIgnoreNextOverrun(true),
-#ifdef FAST_THREAD_STATISTICS
-    // mOldLoad
-    mOldLoadValid(false),
-    mBounds(0),
-    mFull(false),
-    // mTcu
-#endif
-    mColdGen(0),
-    mIsWarm(false),
-    /* mMeasuredWarmupTs({0, 0}), */
-    mWarmupCycles(0),
-    mWarmupConsecutiveInRangeCycles(0),
-    mTimestampStatus(INVALID_OPERATION),
-
-    mCommand(FastThreadState::INITIAL),
-#if 0
-    frameCount(0),
-#endif
-    mAttemptedWrite(false)
-    // mCycleMs(cycleMs)
-    // mLoadUs(loadUs)
+FastThread::FastThread(const char *cycleMs, const char *loadUs) : Thread(false /*canCallJava*/)
 {
-    mOldTs.tv_sec = 0;
-    mOldTs.tv_nsec = 0;
-    mMeasuredWarmupTs.tv_sec = 0;
-    mMeasuredWarmupTs.tv_nsec = 0;
     strlcpy(mCycleMs, cycleMs, sizeof(mCycleMs));
     strlcpy(mLoadUs, loadUs, sizeof(mLoadUs));
 }
 
-FastThread::~FastThread()
-{
-}
-
 bool FastThread::threadLoop()
 {
     // LOGT now works even if tlNBLogWriter is nullptr, but we're considering changing that,
     // so this initialization permits a future change to remove the check for nullptr.
-    tlNBLogWriter = mDummyNBLogWriter.get();
+    aflog::setThreadWriter(mDummyNBLogWriter.get());
     for (;;) {
 
         // either nanosleep, sched_yield, or busy wait
         if (mSleepNs >= 0) {
             if (mSleepNs > 0) {
                 ALOG_ASSERT(mSleepNs < 1000000000);
-                const struct timespec req = {0, mSleepNs};
-                nanosleep(&req, NULL);
+                const struct timespec req = {
+                    0, // tv_sec
+                    static_cast<long>(mSleepNs) // NOLINT(google-runtime-int)
+                };
+                nanosleep(&req, nullptr);
             } else {
                 sched_yield();
             }
@@ -110,7 +69,7 @@
 
         // poll for state change
         const FastThreadState *next = poll();
-        if (next == NULL) {
+        if (next == nullptr) {
             // continue to use the default initial state until a real state is available
             // FIXME &sInitial not available, should save address earlier
             //ALOG_ASSERT(mCurrent == &sInitial && previous == &sInitial);
@@ -121,10 +80,11 @@
         if (next != mCurrent) {
 
             // As soon as possible of learning of a new dump area, start using it
-            mDumpState = next->mDumpState != NULL ? next->mDumpState : mDummyDumpState;
-            tlNBLogWriter = next->mNBLogWriter != NULL ?
+            mDumpState = next->mDumpState != nullptr ? next->mDumpState : mDummyDumpState;
+            NBLog::Writer * const writer = next->mNBLogWriter != nullptr ?
                     next->mNBLogWriter : mDummyNBLogWriter.get();
-            setNBLogWriter(tlNBLogWriter); // This is used for debugging only
+            aflog::setThreadWriter(writer);
+            setNBLogWriter(writer); // This is used for debugging only
 
             // We want to always have a valid reference to the previous (non-idle) state.
             // However, the state queue only guarantees access to current and previous states.
@@ -149,7 +109,7 @@
             mCurrent = next;
         }
 #if !LOG_NDEBUG
-        next = NULL;    // not referenced again
+        next = nullptr;    // not referenced again
 #endif
 
         mDumpState->mCommand = mCommand;
@@ -167,12 +127,12 @@
             // FIXME consider checking previous state and only perform if previous != COLD_IDLE
             if (mCurrent->mColdGen != mColdGen) {
                 int32_t *coldFutexAddr = mCurrent->mColdFutexAddr;
-                ALOG_ASSERT(coldFutexAddr != NULL);
-                int32_t old = android_atomic_dec(coldFutexAddr);
+                ALOG_ASSERT(coldFutexAddr != nullptr);
+                const int32_t old = android_atomic_dec(coldFutexAddr);
                 if (old <= 0) {
-                    syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
+                    syscall(__NR_futex, coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, nullptr);
                 }
-                int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
+                const int policy = sched_getscheduler(0) & ~SCHED_RESET_ON_FORK;
                 if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
                     ALOGE("did not receive expected priority boost on time");
                 }
@@ -224,7 +184,7 @@
         if (rc == 0) {
             if (mOldTsValid) {
                 time_t sec = newTs.tv_sec - mOldTs.tv_sec;
-                long nsec = newTs.tv_nsec - mOldTs.tv_nsec;
+                auto nsec = newTs.tv_nsec - mOldTs.tv_nsec;
                 ALOGE_IF(sec < 0 || (sec == 0 && nsec < 0),
                         "clock_gettime(CLOCK_MONOTONIC) failed: was %ld.%09ld but now %ld.%09ld",
                         mOldTs.tv_sec, mOldTs.tv_nsec, newTs.tv_sec, newTs.tv_nsec);
@@ -267,7 +227,7 @@
                 mSleepNs = -1;
                 if (mIsWarm) {
                     if (sec > 0 || nsec > mUnderrunNs) {
-                        ATRACE_NAME("underrun");
+                        ATRACE_NAME("underrun");   // NOLINT(misc-const-correctness)
                         // FIXME only log occasionally
                         ALOGV("underrun: time since last cycle %d.%03ld sec",
                                 (int) sec, nsec / 1000000L);
@@ -298,7 +258,7 @@
 #ifdef FAST_THREAD_STATISTICS
                 if (mIsWarm) {
                     // advance the FIFO queue bounds
-                    size_t i = mBounds & (mDumpState->mSamplingN - 1);
+                    const size_t i = mBounds & (mDumpState->mSamplingN - 1);
                     mBounds = (mBounds & 0xFFFF0000) | ((mBounds + 1) & 0xFFFF);
                     if (mFull) {
                         //mBounds += 0x10000;
diff --git a/services/audioflinger/fastpath/FastThread.h b/services/audioflinger/fastpath/FastThread.h
new file mode 100644
index 0000000..1f46b29
--- /dev/null
+++ b/services/audioflinger/fastpath/FastThread.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "Configuration.h"
+#ifdef CPU_FREQUENCY_STATISTICS
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+#include <utils/Thread.h>
+#include "FastThreadState.h"
+
+namespace android {
+
+// FastThread is the common abstract base class of FastMixer and FastCapture
+class FastThread : public Thread {
+
+public:
+            FastThread(const char *cycleMs, const char *loadUs);
+
+private:
+    // implement Thread::threadLoop()
+    bool threadLoop() override;
+
+protected:
+    // callouts to subclass in same lexical order as they were in original FastMixer.cpp
+    // FIXME need comments
+    virtual const FastThreadState *poll() = 0;
+    virtual void setNBLogWriter(NBLog::Writer *logWriter __unused) { }
+    virtual void onIdle() = 0;
+    virtual void onExit() = 0;
+    virtual bool isSubClassCommand(FastThreadState::Command command) = 0;
+    virtual void onStateChange() = 0;
+    virtual void onWork() = 0;
+
+    // FIXME these former local variables need comments
+    const FastThreadState*  mPrevious = nullptr;
+    const FastThreadState*  mCurrent = nullptr;
+    struct timespec mOldTs{};
+    bool            mOldTsValid = false;
+    int64_t         mSleepNs = -1;     // -1: busy wait, 0: sched_yield, > 0: nanosleep
+    int64_t         mPeriodNs = 0;     // expected period; the time required to
+                                       // render one mix buffer
+    int64_t         mUnderrunNs = 0;   // underrun likely when write cycle
+                                       // is greater than this value
+    int64_t         mOverrunNs = 0;    // overrun likely when write cycle is less than this value
+    int64_t         mForceNs = 0;      // if overrun detected,
+                                       // force the write cycle to take this much time
+    int64_t         mWarmupNsMin = 0;  // warmup complete when write cycle is greater
+                                       //  than or equal to this value
+    int64_t         mWarmupNsMax = INT64_MAX;  // and less than or equal to this value
+    FastThreadDumpState* mDummyDumpState = nullptr;
+    FastThreadDumpState* mDumpState = nullptr;
+    bool            mIgnoreNextOverrun = true; // used to ignore initial overrun
+                                               //  and first after an underrun
+#ifdef FAST_THREAD_STATISTICS
+    struct timespec mOldLoad;       // previous value of clock_gettime(CLOCK_THREAD_CPUTIME_ID)
+    bool            mOldLoadValid = false;  // whether oldLoad is valid
+    uint32_t        mBounds = 0;
+    bool            mFull = false;        // whether we have collected at least mSamplingN samples
+#ifdef CPU_FREQUENCY_STATISTICS
+    ThreadCpuUsage  mTcu;           // for reading the current CPU clock frequency in kHz
+#endif
+#endif
+    unsigned        mColdGen = 0;       // last observed mColdGen
+    bool            mIsWarm = false;        // true means ready to mix,
+                                    // false means wait for warmup before mixing
+    struct timespec   mMeasuredWarmupTs{};  // how long did it take for warmup to complete
+    uint32_t          mWarmupCycles = 0;  // counter of number of loop cycles during warmup phase
+    uint32_t          mWarmupConsecutiveInRangeCycles = 0; // number of consecutive cycles in range
+    const sp<NBLog::Writer> mDummyNBLogWriter{new NBLog::Writer()};
+    status_t          mTimestampStatus = INVALID_OPERATION;
+
+    FastThreadState::Command mCommand = FastThreadState::INITIAL;
+    bool            mAttemptedWrite = false;
+
+    // init in constructor
+    char            mCycleMs[16];   // cycle_ms + suffix
+    char            mLoadUs[16];    // load_us + suffix
+
+};  // class FastThread
+
+}  // namespace android
diff --git a/services/audioflinger/FastThreadDumpState.cpp b/services/audioflinger/fastpath/FastThreadDumpState.cpp
similarity index 78%
rename from services/audioflinger/FastThreadDumpState.cpp
rename to services/audioflinger/fastpath/FastThreadDumpState.cpp
index e91073f..747cb9e 100644
--- a/services/audioflinger/FastThreadDumpState.cpp
+++ b/services/audioflinger/fastpath/FastThreadDumpState.cpp
@@ -19,32 +19,20 @@
 
 namespace android {
 
-FastThreadDumpState::FastThreadDumpState() :
-    mCommand(FastThreadState::INITIAL), mUnderruns(0), mOverruns(0),
-    /* mMeasuredWarmupTs({0, 0}), */
-    mWarmupCycles(0)
-#ifdef FAST_THREAD_STATISTICS
-    , mSamplingN(0), mBounds(0)
-#endif
+FastThreadDumpState::FastThreadDumpState()
 {
-    mMeasuredWarmupTs.tv_sec = 0;
-    mMeasuredWarmupTs.tv_nsec = 0;
 #ifdef FAST_THREAD_STATISTICS
     increaseSamplingN(1);
 #endif
 }
 
-FastThreadDumpState::~FastThreadDumpState()
-{
-}
-
 #ifdef FAST_THREAD_STATISTICS
 void FastThreadDumpState::increaseSamplingN(uint32_t samplingN)
 {
     if (samplingN <= mSamplingN || samplingN > kSamplingN || roundup(samplingN) != samplingN) {
         return;
     }
-    uint32_t additional = samplingN - mSamplingN;
+    const uint32_t additional = samplingN - mSamplingN;
     // sample arrays aren't accessed atomically with respect to the bounds,
     // so clearing reduces chance for dumpsys to read random uninitialized samples
     memset(&mMonotonicNs[mSamplingN], 0, sizeof(mMonotonicNs[0]) * additional);
diff --git a/services/audioflinger/FastThreadDumpState.h b/services/audioflinger/fastpath/FastThreadDumpState.h
similarity index 83%
rename from services/audioflinger/FastThreadDumpState.h
rename to services/audioflinger/fastpath/FastThreadDumpState.h
index 0b20e55..b7bc404 100644
--- a/services/audioflinger/FastThreadDumpState.h
+++ b/services/audioflinger/fastpath/FastThreadDumpState.h
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+#pragma once
+
+#include <type_traits>
 
 #include "Configuration.h"
 #include "FastThreadState.h"
@@ -30,13 +31,12 @@
 // It has a different lifetime than the FastThread, and so it can't be a member of FastThread.
 struct FastThreadDumpState {
     FastThreadDumpState();
-    /*virtual*/ ~FastThreadDumpState();
 
-    FastThreadState::Command mCommand;   // current command
-    uint32_t mUnderruns;        // total number of underruns
-    uint32_t mOverruns;         // total number of overruns
-    struct timespec mMeasuredWarmupTs;  // measured warmup time
-    uint32_t mWarmupCycles;     // number of loop cycles required to warmup
+    FastThreadState::Command mCommand = FastThreadState::INITIAL;  // current command
+    uint32_t mUnderruns = 0;        // total number of underruns
+    uint32_t mOverruns = 0;         // total number of overruns
+    struct timespec mMeasuredWarmupTs{};  // measured warmup time
+    uint32_t mWarmupCycles = 0;     // number of loop cycles required to warmup
 
 #ifdef FAST_THREAD_STATISTICS
     // Recently collected samples of per-cycle monotonic time, thread CPU time, and CPU frequency.
@@ -48,12 +48,12 @@
     // This value was chosen such that each array uses 1 small page (4 Kbytes).
     static const uint32_t kSamplingNforLowRamDevice = 0x400;
     // Corresponding runtime maximum size of sample arrays, must be a power of 2 <= kSamplingN.
-    uint32_t mSamplingN;
+    uint32_t mSamplingN = 0;
     // The bounds define the interval of valid samples, and are represented as follows:
     //      newest open (excluded) endpoint   = lower 16 bits of bounds, modulo N
     //      oldest closed (included) endpoint = upper 16 bits of bounds, modulo N
     // Number of valid samples is newest - oldest.
-    uint32_t mBounds;                   // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
+    uint32_t mBounds = 0;               // bounds for mMonotonicNs, mThreadCpuNs, and mCpukHz
     // The elements in the *Ns arrays are in units of nanoseconds <= 3999999999.
     uint32_t mMonotonicNs[kSamplingN];  // delta monotonic (wall clock) time
     uint32_t mLoadNs[kSamplingN];       // delta CPU load in time
@@ -67,6 +67,7 @@
 
 };  // struct FastThreadDumpState
 
-}  // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadDumpState>);
 
-#endif  // ANDROID_AUDIO_FAST_THREAD_DUMP_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/FastThreadState.cpp b/services/audioflinger/fastpath/FastThreadState.cpp
similarity index 84%
rename from services/audioflinger/FastThreadState.cpp
rename to services/audioflinger/fastpath/FastThreadState.cpp
index ad5f31f..dfe8e65 100644
--- a/services/audioflinger/FastThreadState.cpp
+++ b/services/audioflinger/fastpath/FastThreadState.cpp
@@ -19,16 +19,6 @@
 
 namespace android {
 
-FastThreadState::FastThreadState() :
-    mCommand(INITIAL), mColdFutexAddr(NULL), mColdGen(0), mDumpState(NULL), mNBLogWriter(NULL)
-
-{
-}
-
-FastThreadState::~FastThreadState()
-{
-}
-
 // static
 const char *FastThreadState::commandToString(FastThreadState::Command command)
 {
@@ -38,7 +28,7 @@
     case FastThreadState::COLD_IDLE:    return "COLD_IDLE";
     case FastThreadState::EXIT:         return "EXIT";
     }
-    return NULL;
+    return nullptr;
 }
 
 }   // namespace android
diff --git a/services/audioflinger/FastThreadState.h b/services/audioflinger/fastpath/FastThreadState.h
similarity index 69%
rename from services/audioflinger/FastThreadState.h
rename to services/audioflinger/fastpath/FastThreadState.h
index 9fb4e06..8e5bedd 100644
--- a/services/audioflinger/FastThreadState.h
+++ b/services/audioflinger/fastpath/FastThreadState.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_FAST_THREAD_STATE_H
-#define ANDROID_AUDIO_FAST_THREAD_STATE_H
+#pragma once
 
+#include <type_traits>
 #include "Configuration.h"
 #include <stdint.h>
 #include <media/nblog/NBLog.h>
@@ -27,10 +27,7 @@
 
 // Represents a single state of a FastThread
 struct FastThreadState {
-                FastThreadState();
-    /*virtual*/ ~FastThreadState();
-
-    typedef uint32_t Command;
+    using Command = uint32_t;
     static const Command
         INITIAL = 0,            // used only for the initial state
         HOT_IDLE = 1,           // do nothing
@@ -38,18 +35,20 @@
         IDLE = 3,               // either HOT_IDLE or COLD_IDLE
         EXIT = 4;               // exit from thread
         // additional values defined per subclass
-    Command     mCommand;       // current command
-    int32_t*    mColdFutexAddr; // for COLD_IDLE only, pointer to the associated futex
-    unsigned    mColdGen;       // increment when COLD_IDLE is requested so it's only performed once
+    Command     mCommand = INITIAL;       // current command
+    int32_t*    mColdFutexAddr = nullptr; // for COLD_IDLE only, pointer to the associated futex
+    unsigned    mColdGen = 0;             // increment when COLD_IDLE is requested
+                                          // so it's only performed once
 
     // This might be a one-time configuration rather than per-state
-    FastThreadDumpState* mDumpState; // if non-NULL, then update dump state periodically
-    NBLog::Writer* mNBLogWriter; // non-blocking logger
+    FastThreadDumpState* mDumpState = nullptr; // if non-NULL, then update dump state periodically
+    NBLog::Writer* mNBLogWriter = nullptr; // non-blocking logger
 
     // returns NULL if command belongs to a subclass
     static const char *commandToString(Command command);
 };  // struct FastThreadState
 
-}  // namespace android
+// No virtuals.
+static_assert(!std::is_polymorphic_v<FastThreadState>);
 
-#endif  // ANDROID_AUDIO_FAST_THREAD_STATE_H
+}  // namespace android
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/fastpath/StateQueue.cpp
similarity index 82%
rename from services/audioflinger/StateQueue.cpp
rename to services/audioflinger/fastpath/StateQueue.cpp
index 38ce2c2..e896d29 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/fastpath/StateQueue.cpp
@@ -38,23 +38,6 @@
 }
 #endif
 
-// Constructor and destructor
-
-template<typename T> StateQueue<T>::StateQueue() :
-    mAck(NULL), mCurrent(NULL),
-    mMutating(&mStates[0]), mExpecting(NULL),
-    mInMutation(false), mIsDirty(false), mIsInitialized(false)
-#ifdef STATE_QUEUE_DUMP
-    , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump)
-#endif
-{
-    atomic_init(&mNext, static_cast<uintptr_t>(0));
-}
-
-template<typename T> StateQueue<T>::~StateQueue()
-{
-}
-
 // Observer APIs
 
 template<typename T> const T* StateQueue<T>::poll()
@@ -112,7 +95,7 @@
 #endif
 
         // wait for prior push to be acknowledged
-        if (mExpecting != NULL) {
+        if (mExpecting != nullptr) {
 #ifdef STATE_QUEUE_DUMP
             unsigned count = 0;
 #endif
@@ -120,7 +103,7 @@
                 const T *ack = (const T *) mAck;    // no additional barrier needed
                 if (ack == mExpecting) {
                     // unnecessary as we're about to rewrite
-                    //mExpecting = NULL;
+                    //mExpecting = nullptr;
                     break;
                 }
                 if (block == BLOCK_NEVER) {
@@ -132,7 +115,7 @@
                 }
                 ++count;
 #endif
-                nanosleep(&req, NULL);
+                nanosleep(&req, nullptr);
             }
 #ifdef STATE_QUEUE_DUMP
             if (count > 1) {
@@ -156,14 +139,14 @@
 
     // optionally wait for this push or a prior push to be acknowledged
     if (block == BLOCK_UNTIL_ACKED) {
-        if (mExpecting != NULL) {
+        if (mExpecting != nullptr) {
 #ifdef STATE_QUEUE_DUMP
             unsigned count = 0;
 #endif
             for (;;) {
                 const T *ack = (const T *) mAck;    // no additional barrier needed
                 if (ack == mExpecting) {
-                    mExpecting = NULL;
+                    mExpecting = nullptr;
                     break;
                 }
 #ifdef STATE_QUEUE_DUMP
@@ -172,7 +155,7 @@
                 }
                 ++count;
 #endif
-                nanosleep(&req, NULL);
+                nanosleep(&req, nullptr);
             }
 #ifdef STATE_QUEUE_DUMP
             if (count > 1) {
@@ -187,9 +170,14 @@
 
 }   // namespace android
 
-// Hack to avoid explicit template instantiation of
-// template class StateQueue<FastCaptureState>;
-// template class StateQueue<FastMixerState>;
-#ifdef STATE_QUEUE_INSTANTIATIONS
-#include STATE_QUEUE_INSTANTIATIONS  // NOLINT(bugprone-suspicious-include)
-#endif
+// Instantiate StateQueue template for the types we need.
+// This needs to be done in the same translation unit as the template
+// method definitions above.
+
+#include "FastCaptureState.h"
+#include "FastMixerState.h"
+
+namespace android {
+template class StateQueue<FastCaptureState>;
+template class StateQueue<FastMixerState>;
+}   // namespace android
diff --git a/services/audioflinger/StateQueue.h b/services/audioflinger/fastpath/StateQueue.h
similarity index 91%
rename from services/audioflinger/StateQueue.h
rename to services/audioflinger/fastpath/StateQueue.h
index 27f6a28..29d1809 100644
--- a/services/audioflinger/StateQueue.h
+++ b/services/audioflinger/fastpath/StateQueue.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_AUDIO_STATE_QUEUE_H
-#define ANDROID_AUDIO_STATE_QUEUE_H
+#pragma once
 
 #include <stdatomic.h>
 
@@ -127,8 +126,7 @@
 template<typename T> class StateQueue {
 
 public:
-            StateQueue();
-    virtual ~StateQueue();
+    virtual ~StateQueue() = default;  // why is this virtual?
 
     // Observer APIs
 
@@ -188,28 +186,29 @@
     T                 mStates[kN];      // written by mutator, read by observer
 
     // "volatile" is meaningless with SMP, but here it indicates that we're using atomic ops
-    atomic_uintptr_t  mNext; // written by mutator to advance next, read by observer
-    volatile const T* mAck;  // written by observer to acknowledge advance of next, read by mutator
+    atomic_uintptr_t  mNext{}; // written by mutator to advance next, read by observer
+    volatile const T* mAck = nullptr;  // written by observer to acknowledge advance of next,
+                                       // read by mutator
 
     // only used by observer
-    const T*          mCurrent;         // most recent value returned by poll()
+    const T*    mCurrent = nullptr;     // most recent value returned by poll()
 
     // only used by mutator
-    T*                mMutating;        // where updates by mutator are done in place
-    const T*          mExpecting;       // what the mutator expects mAck to be set to
-    bool              mInMutation;      // whether we're currently in the middle of a mutation
-    bool              mIsDirty;         // whether mutating state has been modified since last push
-    bool              mIsInitialized;   // whether mutating state has been initialized yet
+    T*          mMutating{&mStates[0]}; // where updates by mutator are done in place
+    const T*    mExpecting = nullptr;   // what the mutator expects mAck to be set to
+    bool        mInMutation = false;    // whether we're currently in the middle of a mutation
+    bool        mIsDirty = false;       // whether mutating state has been modified since last push
+    bool        mIsInitialized = false; // whether mutating state has been initialized yet
 
 #ifdef STATE_QUEUE_DUMP
     StateQueueObserverDump  mObserverDummyDump; // default area for observer dump if not set
-    StateQueueObserverDump* mObserverDump;      // pointer to active observer dump, always non-NULL
+    // pointer to active observer dump, always non-nullptr
+    StateQueueObserverDump* mObserverDump{&mObserverDummyDump};
     StateQueueMutatorDump   mMutatorDummyDump;  // default area for mutator dump if not set
-    StateQueueMutatorDump*  mMutatorDump;       // pointer to active mutator dump, always non-NULL
+    // pointer to active mutator dump, always non-nullptr
+    StateQueueMutatorDump*  mMutatorDump{&mMutatorDummyDump};
 #endif
 
 };  // class StateQueue
 
 }   // namespace android
-
-#endif  // ANDROID_AUDIO_STATE_QUEUE_H
diff --git a/services/audioflinger/timing/Android.bp b/services/audioflinger/timing/Android.bp
new file mode 100644
index 0000000..269f796
--- /dev/null
+++ b/services/audioflinger/timing/Android.bp
@@ -0,0 +1,32 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_library {
+    name: "libaudioflinger_timing",
+
+    defaults: [
+        "audioflinger_flags_defaults",
+    ],
+
+    host_supported: true,
+
+    srcs: [
+        "MonotonicFrameCounter.cpp",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+}
diff --git a/services/audioflinger/timing/MonotonicFrameCounter.cpp b/services/audioflinger/timing/MonotonicFrameCounter.cpp
new file mode 100644
index 0000000..286f549
--- /dev/null
+++ b/services/audioflinger/timing/MonotonicFrameCounter.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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_NDEBUG 0
+#define LOG_TAG "MonotonicFrameCounter"
+
+#include <utils/Log.h>
+#include "MonotonicFrameCounter.h"
+
+namespace android::audioflinger {
+
+int64_t MonotonicFrameCounter::updateAndGetMonotonicFrameCount(
+        int64_t newFrameCount, int64_t newTime) {
+    if (newFrameCount < 0 || newTime < 0) {
+        const auto result = getLastReportedFrameCount();
+        ALOGW("%s: invalid (frame, time) pair newFrameCount:%lld newFrameCount:%lld,"
+                " using %lld as frameCount",
+                __func__, (long long) newFrameCount, (long long)newFrameCount,
+                (long long)result);
+        return result;
+    }
+    if (newFrameCount < mLastReceivedFrameCount) {
+        const auto result = getLastReportedFrameCount();
+        ALOGW("%s: retrograde newFrameCount:%lld < mLastReceivedFrameCount:%lld,"
+                " ignoring, returning %lld as frameCount",
+                __func__, (long long) newFrameCount, (long long)mLastReceivedFrameCount,
+                (long long)result);
+        return result;
+    }
+    // Input looks fine.
+    // For better granularity, we could consider extrapolation on newTime.
+    mLastReceivedFrameCount = newFrameCount;
+    return getLastReportedFrameCount();
+}
+
+int64_t MonotonicFrameCounter::onFlush() {
+    ALOGV("%s: Updating mOffsetFrameCount:%lld with mLastReceivedFrameCount:%lld",
+            __func__, (long long)mOffsetFrameCount, (long long)mLastReceivedFrameCount);
+    mOffsetFrameCount += mLastReceivedFrameCount;
+    mLastReceivedFrameCount = 0;
+    return mOffsetFrameCount;
+}
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/MonotonicFrameCounter.h b/services/audioflinger/timing/MonotonicFrameCounter.h
new file mode 100644
index 0000000..0ea9510
--- /dev/null
+++ b/services/audioflinger/timing/MonotonicFrameCounter.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+namespace android::audioflinger {
+
+/**
+ * MonotonicFrameCounter
+ *
+ * Advances a monotonic frame count based on input timestamp pairs (frames, time).
+ * It takes into account a possible flush, which will "reset" the frames to 0.
+ *
+ * This class is used to drive VolumeShaper volume automation.
+ *
+ * The timestamps provided in updateAndGetMonotonicFrameCount should
+ * be of sufficient granularity for the purpose at hand.  Currently no temporal
+ * extrapolation is done.
+ *
+ * This class is not thread safe.
+ */
+class MonotonicFrameCounter {
+public:
+    /**
+     * Receives a new timestamp pair (frames, time) and returns a monotonic frameCount.
+     *
+     * \param newFrameCount the frameCount currently played.
+     * \param newTime       the time corresponding to the frameCount.
+     * \return              a monotonic frame count usable for automation timing.
+     */
+    int64_t updateAndGetMonotonicFrameCount(int64_t newFrameCount, int64_t newTime);
+
+    /**
+     * Notifies when a flush occurs, whereupon the received frameCount sequence restarts at 0.
+     *
+     * \return the last reported frameCount.
+     */
+    int64_t onFlush();
+
+    /**
+     * Returns the received (input) frameCount to reported (output) frameCount offset.
+     *
+     * This offset is sufficient to ensure monotonicity after flush is called,
+     * suitability for any other purpose is *not* guaranteed.
+     */
+    int64_t getOffsetFrameCount() const { return mOffsetFrameCount; }
+
+    /**
+     * Returns the last received frameCount.
+     */
+    int64_t getLastReceivedFrameCount() const {
+        return mLastReceivedFrameCount;
+    }
+
+    /**
+     * Returns the last reported frameCount from updateAndGetMonotonicFrameCount().
+     */
+    int64_t getLastReportedFrameCount() const {
+        // This is consistent after onFlush().
+        return mOffsetFrameCount + mLastReceivedFrameCount;
+    }
+
+private:
+    int64_t mOffsetFrameCount = 0;
+    int64_t mLastReceivedFrameCount = 0;
+};
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/SyncEvent.h b/services/audioflinger/timing/SyncEvent.h
new file mode 100644
index 0000000..b5a3b40
--- /dev/null
+++ b/services/audioflinger/timing/SyncEvent.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <mutex>
+
+#include <media/AudioSystem.h>
+#include <utils/RefBase.h>
+
+namespace android::audioflinger {
+
+class SyncEvent;
+using SyncEventCallback = std::function<void(const wp<SyncEvent>& event)>;
+
+class SyncEvent : public RefBase {
+public:
+    SyncEvent(AudioSystem::sync_event_t type,
+              audio_session_t triggerSession,
+              audio_session_t listenerSession,
+              const SyncEventCallback& callBack,
+              const wp<RefBase>& cookie)
+    : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
+      mCookie(cookie), mCallback(callBack)
+    {}
+
+    void trigger() {
+        std::lock_guard l(mLock);
+        if (mCallback) mCallback(wp<SyncEvent>::fromExisting(this));
+    }
+
+    bool isCancelled() const {
+        std::lock_guard l(mLock);
+        return mCallback == nullptr;
+    }
+
+    void cancel() {
+        std::lock_guard l(mLock);
+        mCallback = nullptr;
+    }
+
+    AudioSystem::sync_event_t type() const { return mType; }
+    audio_session_t triggerSession() const { return mTriggerSession; }
+    audio_session_t listenerSession() const { return mListenerSession; }
+    const wp<RefBase>& cookie() const { return mCookie; }
+
+private:
+      const AudioSystem::sync_event_t mType;
+      const audio_session_t mTriggerSession;
+      const audio_session_t mListenerSession;
+      const wp<RefBase> mCookie;
+      mutable std::mutex mLock;
+      SyncEventCallback mCallback GUARDED_BY(mLock);
+};
+
+} // namespace android::audioflinger
diff --git a/services/audioflinger/timing/SynchronizedRecordState.h b/services/audioflinger/timing/SynchronizedRecordState.h
new file mode 100644
index 0000000..f40d41b
--- /dev/null
+++ b/services/audioflinger/timing/SynchronizedRecordState.h
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "SyncEvent.h"
+
+#pragma push_macro("LOG_TAG")
+#undef LOG_TAG
+#define LOG_TAG "SynchronizedRecordState"
+
+namespace android::audioflinger {
+
+class SynchronizedRecordState {
+public:
+    explicit SynchronizedRecordState(uint32_t sampleRate)
+        : mSampleRate(sampleRate)
+        {}
+
+    void clear() {
+        std::lock_guard lg(mLock);
+        clear_l();
+    }
+
+    // Called by the RecordThread when recording is starting.
+    void startRecording(const sp<SyncEvent>& event) {
+        std::lock_guard lg(mLock);
+        mSyncStartEvent = event;
+        // Sync event can be cancelled by the trigger session if the track is not in a
+        // compatible state in which case we start record immediately
+        if (mSyncStartEvent->isCancelled()) {
+            clear_l();
+        } else {
+            mFramesToDrop = -(ssize_t)
+                ((AudioSystem::kSyncRecordStartTimeOutMs * mSampleRate) / 1000);
+        }
+    }
+
+    // Invoked by SyncEvent callback.
+    void onPlaybackFinished(const sp<SyncEvent>& event, size_t framesToDrop = 1) {
+        std::lock_guard lg(mLock);
+        if (event == mSyncStartEvent) {
+            mFramesToDrop = framesToDrop;  // compute this
+            ALOGV("%s: framesToDrop:%zd", __func__, mFramesToDrop);
+        }
+    }
+
+    // Returns the current FramesToDrop counter
+    //
+    //   if <0 waiting (drop the frames)
+    //   if >0 draining (drop the frames)
+    //    else if ==0 proceed to record.
+    ssize_t updateRecordFrames(size_t frames) {
+        std::lock_guard lg(mLock);
+        if (mFramesToDrop > 0) {
+            // we've been triggered, we count down for start delay
+            ALOGV("%s: trigger countdown %zd by %zu frames", __func__, mFramesToDrop, frames);
+            mFramesToDrop -= (ssize_t)frames;
+            if (mFramesToDrop <= 0) clear_l();
+        } else if (mFramesToDrop < 0) {
+            // we're waiting to be triggered.
+            // ALOGD("%s: timeout countup %zd with %zu frames", __func__, mFramesToDrop, frames);
+            mFramesToDrop += (ssize_t)frames;
+            if (mFramesToDrop >= 0 || !mSyncStartEvent || mSyncStartEvent->isCancelled()) {
+                ALOGW("Synced record %s, trigger session %d",
+                        (mFramesToDrop >= 0) ? "timed out" : "cancelled",
+                        (mSyncStartEvent) ? mSyncStartEvent->triggerSession()
+                                          : AUDIO_SESSION_NONE);
+                 clear_l();
+            }
+        }
+        return mFramesToDrop;
+    }
+
+private:
+    const uint32_t mSampleRate;
+
+    std::mutex mLock;
+    // number of captured frames to drop after the start sync event has been received.
+    // when < 0, maximum frames to drop before starting capture even if sync event is
+    // not received
+    ssize_t mFramesToDrop GUARDED_BY(mLock) = 0;
+
+    // sync event triggering actual audio capture. Frames read before this event will
+    // be dropped and therefore not read by the application.
+    sp<SyncEvent> mSyncStartEvent GUARDED_BY(mLock);
+
+    void clear_l() REQUIRES(mLock) {
+        if (mSyncStartEvent) {
+            mSyncStartEvent->cancel();
+            mSyncStartEvent.clear();
+        }
+        mFramesToDrop = 0;
+    }
+};
+
+} // namespace android::audioflinger
+
+#pragma pop_macro("LOG_TAG")
diff --git a/services/audioflinger/timing/tests/Android.bp b/services/audioflinger/timing/tests/Android.bp
new file mode 100644
index 0000000..d1e5563
--- /dev/null
+++ b/services/audioflinger/timing/tests/Android.bp
@@ -0,0 +1,79 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_services_audioflinger_license"],
+}
+
+cc_test {
+    name: "mediasyncevent_tests",
+
+    host_supported: true,
+
+    srcs: [
+        "mediasyncevent_tests.cpp"
+    ],
+
+    header_libs: [
+        "libaudioclient_headers",
+    ],
+
+    static_libs: [
+        "liblog",
+        "libutils", // RefBase
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
+
+cc_test {
+    name: "monotonicframecounter_tests",
+
+    host_supported: true,
+
+    srcs: [
+        "monotonicframecounter_tests.cpp"
+    ],
+
+    static_libs: [
+        "libaudioflinger_timing",
+        "liblog",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+}
+
+cc_test {
+     name: "synchronizedrecordstate_tests",
+
+     host_supported: true,
+
+     srcs: [
+         "synchronizedrecordstate_tests.cpp"
+     ],
+
+     header_libs: [
+         "libaudioclient_headers",
+     ],
+
+     static_libs: [
+         "liblog",
+         "libutils", // RefBase
+     ],
+
+     cflags: [
+         "-Wall",
+         "-Werror",
+         "-Wextra",
+     ],
+ }
\ No newline at end of file
diff --git a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
new file mode 100644
index 0000000..2922d90
--- /dev/null
+++ b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "mediasyncevent_tests"
+
+#include "../SyncEvent.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(MediaSyncEventTests, Basic) {
+    struct Cookie : public RefBase {};
+
+    // These variables are set by trigger().
+    bool triggered = false;
+    wp<SyncEvent> param;
+
+    constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+    constexpr auto triggerSession = audio_session_t(10);
+    constexpr auto listenerSession = audio_session_t(11);
+    const SyncEventCallback callback =
+            [&](const wp<SyncEvent>& event) {
+                triggered = true;
+                param = event;
+            };
+    const auto cookie = sp<Cookie>::make();
+
+    // Since the callback uses a weak pointer to this,
+    // don't allocate on the stack.
+    auto syncEvent = sp<SyncEvent>::make(
+            type,
+            triggerSession,
+            listenerSession,
+            callback,
+            cookie);
+
+    ASSERT_EQ(type, syncEvent->type());
+    ASSERT_EQ(triggerSession, syncEvent->triggerSession());
+    ASSERT_EQ(listenerSession, syncEvent->listenerSession());
+    ASSERT_EQ(cookie, syncEvent->cookie());
+    ASSERT_FALSE(triggered);
+
+    syncEvent->trigger();
+    ASSERT_TRUE(triggered);
+    ASSERT_EQ(param, syncEvent);
+
+    ASSERT_FALSE(syncEvent->isCancelled());
+    syncEvent->cancel();
+    ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+} // namespace
diff --git a/services/audioflinger/timing/tests/monotonicframecounter_tests.cpp b/services/audioflinger/timing/tests/monotonicframecounter_tests.cpp
new file mode 100644
index 0000000..7aaa4fa
--- /dev/null
+++ b/services/audioflinger/timing/tests/monotonicframecounter_tests.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 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_NDEBUG 0
+#define LOG_TAG "monotonicframecounter_tests"
+
+#include "../MonotonicFrameCounter.h"
+
+#include <gtest/gtest.h>
+
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(MonotonicFrameCounterTest, SimpleProgression) {
+    MonotonicFrameCounter monotonicFrameCounter;
+
+    const std::vector<std::pair<int64_t, int64_t>> frametimes{
+        {0, 0}, {100, 100}, {200, 200},
+    };
+
+    int64_t maxReceivedFrameCount = 0;
+    for (const auto& p : frametimes) {
+        maxReceivedFrameCount = std::max(maxReceivedFrameCount, p.first);
+        ASSERT_EQ(p.first,
+                monotonicFrameCounter.updateAndGetMonotonicFrameCount(p.first, p.second));
+    }
+    ASSERT_EQ(maxReceivedFrameCount, monotonicFrameCounter.getLastReportedFrameCount());
+}
+
+TEST(MonotonicFrameCounterTest, InvalidData) {
+    MonotonicFrameCounter monotonicFrameCounter;
+
+    const std::vector<std::pair<int64_t, int64_t>> frametimes{
+        {-1, -1}, {100, 100}, {-1, -1}, {90, 90}, {200, 200},
+    };
+
+    int64_t prevFrameCount = 0;
+    int64_t maxReceivedFrameCount = 0;
+    for (const auto& p : frametimes) {
+        maxReceivedFrameCount = std::max(maxReceivedFrameCount, p.first);
+        const int64_t frameCount =
+                monotonicFrameCounter.updateAndGetMonotonicFrameCount(p.first, p.second);
+        // we must be monotonic
+        ASSERT_GE(frameCount, prevFrameCount);
+        prevFrameCount = frameCount;
+    }
+    ASSERT_EQ(maxReceivedFrameCount, monotonicFrameCounter.getLastReportedFrameCount());
+}
+
+TEST(MonotonicFrameCounterTest, Flush) {
+    MonotonicFrameCounter monotonicFrameCounter;
+
+    // Different playback sequences are separated by a flush.
+    const std::vector<std::vector<std::pair<int64_t, int64_t>>> frameset{
+        {{-1, -1}, {100, 10}, {200, 20}, {300, 30},},
+        {{-1, -1}, {100, 10}, {200, 20}, {300, 30},},
+        {{-1, -1}, {100, 100}, {-1, -1}, {90, 90}, {200, 200},},
+    };
+
+    int64_t prevFrameCount = 0;
+    int64_t maxReceivedFrameCount = 0;
+    int64_t sumMaxReceivedFrameCount = 0;
+    for (const auto& v : frameset) {
+        for (const auto& p : v) {
+            maxReceivedFrameCount = std::max(maxReceivedFrameCount, p.first);
+            const int64_t frameCount =
+                    monotonicFrameCounter.updateAndGetMonotonicFrameCount(p.first, p.second);
+            // we must be monotonic
+            ASSERT_GE(frameCount, prevFrameCount);
+            prevFrameCount = frameCount;
+        }
+        monotonicFrameCounter.onFlush();
+        sumMaxReceivedFrameCount += maxReceivedFrameCount;
+        maxReceivedFrameCount = 0;
+    }
+
+    // On flush we keep a monotonic reported framecount
+    // even though the received framecount resets to 0.
+    // The requirement of equality here is implementation dependent.
+    ASSERT_EQ(sumMaxReceivedFrameCount, monotonicFrameCounter.getLastReportedFrameCount());
+}
+
+}  // namespace
diff --git a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
new file mode 100644
index 0000000..ee5d269
--- /dev/null
+++ b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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_NDEBUG 0
+#define LOG_TAG "synchronizedrecordstate_tests"
+
+#include "../SynchronizedRecordState.h"
+
+#include <gtest/gtest.h>
+
+using namespace android;
+using namespace android::audioflinger;
+
+namespace {
+
+TEST(SynchronizedRecordStateTests, Basic) {
+    struct Cookie : public RefBase {};
+
+    // These variables are set by trigger().
+    bool triggered = false;
+    wp<SyncEvent> param;
+
+    constexpr auto type = AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
+    constexpr auto triggerSession = audio_session_t(10);
+    constexpr auto listenerSession = audio_session_t(11);
+    const SyncEventCallback callback =
+            [&](const wp<SyncEvent>& event) {
+                triggered = true;
+                param = event;
+            };
+    const auto cookie = sp<Cookie>::make();
+
+    // Check timeout.
+    SynchronizedRecordState recordState(48000 /* sampleRate */);
+    auto syncEvent = sp<SyncEvent>::make(
+            type,
+            triggerSession,
+            listenerSession,
+            callback,
+            cookie);
+    recordState.startRecording(syncEvent);
+    recordState.updateRecordFrames(2);
+    ASSERT_FALSE(triggered);
+    ASSERT_EQ(0, recordState.updateRecordFrames(1'000'000'000));
+    ASSERT_FALSE(triggered);
+    ASSERT_TRUE(syncEvent->isCancelled());
+
+    // Check count down after track is complete.
+    syncEvent = sp<SyncEvent>::make(
+                type,
+                triggerSession,
+                listenerSession,
+                callback,
+                cookie);
+    recordState.startRecording(syncEvent);
+    recordState.onPlaybackFinished(syncEvent, 10);
+    ASSERT_EQ(1, recordState.updateRecordFrames(9));
+    ASSERT_FALSE(triggered);
+    ASSERT_EQ(0, recordState.updateRecordFrames(2));
+    ASSERT_FALSE(triggered);
+    ASSERT_TRUE(syncEvent->isCancelled());
+}
+
+}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 0a9e6eb..e170713 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -310,13 +310,13 @@
     virtual status_t listAudioProductStrategies(AudioProductStrategyVector &strategies) = 0;
 
     virtual status_t getProductStrategyFromAudioAttributes(
-            const AudioAttributes &aa, product_strategy_t &productStrategy,
+            const audio_attributes_t &aa, product_strategy_t &productStrategy,
             bool fallbackOnDefault) = 0;
 
     virtual status_t listAudioVolumeGroups(AudioVolumeGroupVector &groups) = 0;
 
     virtual status_t getVolumeGroupFromAudioAttributes(
-            const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault) = 0;
+            const audio_attributes_t &aa, volume_group_t &volumeGroup, bool fallbackOnDefault) = 0;
 
     virtual bool     isCallScreenModeSupported() = 0;
 
@@ -418,6 +418,8 @@
 public:
     virtual ~AudioPolicyClientInterface() {}
 
+    virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig *config) = 0;
+
     //
     // Audio HW module functions
     //
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index 3df23f1..972de02 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",
@@ -30,7 +34,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 b24fce8..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,11 +43,18 @@
     // 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.
+    static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
 
     // 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(
@@ -114,12 +122,6 @@
         mDefaultOutputDevice = defaultDevice;
     }
 
-    bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
-    void setSpeakerDrcEnabled(bool isSpeakerDrcEnabled)
-    {
-        mIsSpeakerDrcEnabled = isSpeakerDrcEnabled;
-    }
-
     bool isCallScreenModeSupported() const { return mIsCallScreenModeSupported; }
     void setCallScreenModeSupported(bool isCallScreenModeSupported)
     {
@@ -135,33 +137,24 @@
     {
         mSurroundFormats = surroundFormats;
     }
-    void setSurroundFormats(SurroundFormats &&surroundFormats)
-    {
-        mSurroundFormats = std::move(surroundFormats);
-    }
 
     void setDefault();
 
 private:
     friend class sp<AudioPolicyConfig>;
 
-    static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
-
     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.
     std::string mEngineLibraryNameSuffix = kDefaultEngineLibraryNameSuffix;
     HwModuleCollection mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
-    DeviceVector mOutputDevices;
-    DeviceVector mInputDevices;
+    DeviceVector mOutputDevices;  // Attached output devices.
+    DeviceVector mInputDevices;   // Attached input devices.
     sp<DeviceDescriptor> mDefaultOutputDevice;
-    // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
-    // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
-    // Note: remove also speaker_drc_enabled from global configuration of XML config file.
-    bool mIsSpeakerDrcEnabled = false;
     bool mIsCallScreenModeSupported = false;
     SurroundFormats mSurroundFormats;
 };
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/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index be13340..329e0ca 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -674,12 +674,6 @@
             }
         }
 
-        // TODO(b/73175392) consider improving the AIDL interface.
-        // Signal closing to A2DP HAL.
-        AudioParameter param;
-        param.add(String8(AudioParameter::keyClosing), String8("true"));
-        mClientInterface->setParameters(mIoHandle, param.toString());
-
         mClientInterface->closeOutput(mIoHandle);
 
         LOG_ALWAYS_FATAL_IF(mProfile->curOpenCount < 1, "%s profile open count %u",
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 575a6c5..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 =
@@ -41,9 +190,8 @@
     auto config = sp<AudioPolicyConfig>::make();
     if (status_t status = config->loadFromXml(filePath, false /*forVts*/); status == NO_ERROR) {
         return config;
-    } else {
-        return createDefault();
     }
+    return createDefault();
 }
 
 // static
@@ -101,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");
@@ -132,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/common/managerdefinitions/src/IOProfile.cpp b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
index 21f2018..2cbdeaa 100644
--- a/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/IOProfile.cpp
@@ -68,7 +68,7 @@
             if (checkExactAudioProfile(&config) != NO_ERROR) {
                 return false;
             }
-        } else if (checkCompatibleAudioProfile(
+        } else if (checkExactAudioProfile(&config) != NO_ERROR && checkCompatibleAudioProfile(
                 myUpdatedSamplingRate, myUpdatedChannelMask, myUpdatedFormat) != NO_ERROR) {
             return false;
         }
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 1b48dc3..3d5c1d2 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -197,7 +197,6 @@
 
     struct Attributes
     {
-        static constexpr const char *speakerDrcEnabled = "speaker_drc_enabled";
         static constexpr const char *callScreenModeSupported= "call_screen_mode_supported";
         static constexpr const char *engineLibrarySuffix = "engine_library";
     };
@@ -770,12 +769,7 @@
     for (const xmlNode *cur = root->xmlChildrenNode; cur != NULL; cur = cur->next) {
         if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(GlobalConfigTraits::tag))) {
             bool value;
-            std::string attr = getXmlAttribute(cur, Attributes::speakerDrcEnabled);
-            if (!attr.empty() &&
-                    convertTo<std::string, bool>(attr, value)) {
-                config->setSpeakerDrcEnabled(value);
-            }
-            attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
+            std::string attr = getXmlAttribute(cur, Attributes::callScreenModeSupported);
             if (!attr.empty() &&
                     convertTo<std::string, bool>(attr, value)) {
                 config->setCallScreenModeSupported(value);
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 de501ee..5f4080e 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>
@@ -110,7 +113,10 @@
     status_t getDevicesForRoleAndStrategy(product_strategy_t strategy, device_role_t role,
             AudioDeviceTypeAddrVector &devices) const override;
 
-    engineConfig::ParsingResult loadAudioPolicyEngineConfig();
+    engineConfig::ParsingResult loadAudioPolicyEngineConfig(
+            const media::audio::common::AudioHalEngineConfig& aidlConfig);
+
+    engineConfig::ParsingResult loadAudioPolicyEngineConfig(const std::string& xmlFilePath = "");
 
     const ProductStrategyMap &getProductStrategies() const { return mProductStrategies; }
 
@@ -167,6 +173,8 @@
     void updateDeviceSelectionCache() override;
 
 private:
+    engineConfig::ParsingResult processParsingResult(engineConfig::ParsingResult&& rawResult);
+
     /**
      * Get media devices as the given role
      *
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 2aa2f9a..1593be0 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -24,7 +24,7 @@
 #include <vector>
 
 #include <HandleGenerator.h>
-#include <media/AudioAttributes.h>
+#include <media/VolumeGroupAttributes.h>
 #include <media/AudioContainers.h>
 #include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioPolicy.h>
@@ -43,25 +43,20 @@
 class ProductStrategy : public virtual RefBase, private HandleGenerator<uint32_t>
 {
 private:
-    struct AudioAttributes {
-        audio_stream_type_t mStream = AUDIO_STREAM_DEFAULT;
-        volume_group_t mVolumeGroup = VOLUME_GROUP_NONE;
-        audio_attributes_t mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
-    };
-
-    using AudioAttributesVector = std::vector<AudioAttributes>;
+    using VolumeGroupAttributesVector = std::vector<VolumeGroupAttributes>;
 
 public:
     ProductStrategy(const std::string &name);
 
-    void addAttributes(const AudioAttributes &audioAttributes);
+    void addAttributes(const VolumeGroupAttributes &volumeGroupAttributes);
 
-    std::vector<android::AudioAttributes> listAudioAttributes() const;
+    std::vector<android::VolumeGroupAttributes> listVolumeGroupAttributes() const;
 
     std::string getName() const { return mName; }
     AttributesVector getAudioAttributes() const;
     product_strategy_t getId() const { return mId; }
     StreamTypeVector getSupportedStreams() const;
+    VolumeGroupAttributesVector getVolumeGroupAttributes() const { return mAttributesVector; }
 
     /**
      * @brief matches checks if the given audio attributes shall follow the strategy.
@@ -69,9 +64,9 @@
      *        If only the usage is available, the check is performed on the usages of the given
      *        attributes, otherwise all fields must match.
      * @param attributes to consider
-     * @return true if attributes matches with the strategy, false otherwise.
+     * @return matching score, negative value if no match.
      */
-    bool matches(const audio_attributes_t attributes) const;
+    int matchesScore(const audio_attributes_t attributes) const;
 
     bool supportStreamType(const audio_stream_type_t &streamType) const;
 
@@ -90,9 +85,6 @@
     DeviceTypeSet getDeviceTypes() const { return mApplicableDevices; }
 
     audio_attributes_t getAttributesForStreamType(audio_stream_type_t stream) const;
-    audio_stream_type_t getStreamTypeForAttributes(const audio_attributes_t &attr) const;
-
-    volume_group_t getVolumeGroupForAttributes(const audio_attributes_t &attr) const;
 
     volume_group_t getVolumeGroupForStreamType(audio_stream_type_t stream) const;
 
@@ -105,7 +97,7 @@
 private:
     std::string mName;
 
-    AudioAttributesVector mAttributesVector;
+    VolumeGroupAttributesVector mAttributesVector;
 
     product_strategy_t mId;
 
@@ -167,6 +159,9 @@
     void dump(String8 *dst, int spaces = 0) const;
 
 private:
+    VolumeGroupAttributes getVolumeGroupAttributesForAttributes(
+            const audio_attributes_t &attr, bool fallbackOnDefault = true) const;
+
     product_strategy_t mDefaultStrategy = PRODUCT_STRATEGY_NONE;
 };
 
diff --git a/services/audiopolicy/engine/common/include/VolumeGroup.h b/services/audiopolicy/engine/common/include/VolumeGroup.h
index 5378f64..f40ab1c 100644
--- a/services/audiopolicy/engine/common/include/VolumeGroup.h
+++ b/services/audiopolicy/engine/common/include/VolumeGroup.h
@@ -39,7 +39,7 @@
     VolumeCurves *getVolumeCurves() { return &mGroupVolumeCurves; }
 
     void addSupportedAttributes(const audio_attributes_t &attr);
-    AttributesVector getSupportedAttributes() const { return mGroupVolumeCurves.getAttributes(); }
+    AttributesVector getSupportedAttributes() const;
 
     void addSupportedStream(audio_stream_type_t stream);
     StreamTypeVector getStreamTypes() const { return mGroupVolumeCurves.getStreamTypes(); }
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index 83a8e4d..adb1ca3 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()
+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(); }),
@@ -145,7 +188,7 @@
     };
     auto addSupportedAttributesToGroup = [](auto &group, auto &volumeGroup, auto &strategy) {
         for (const auto &attr : group.attributesVect) {
-            strategy->addAttributes({group.stream, volumeGroup->getId(), attr});
+            strategy->addAttributes({volumeGroup->getId(), group.stream, attr});
             volumeGroup->addSupportedAttributes(attr);
         }
     };
@@ -158,41 +201,21 @@
         });
         return iter != end(volumeGroups);
     };
-    auto fileExists = [](const char* path) {
-        struct stat fileStat;
-        return stat(path, &fileStat) == 0 && S_ISREG(fileStat.st_mode);
-    };
 
-    auto result = fileExists(engineConfig::DEFAULT_PATH) ?
-            engineConfig::parse(engineConfig::DEFAULT_PATH) : 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);
@@ -284,7 +307,7 @@
     for (const auto &iter : mProductStrategies) {
         const auto &productStrategy = iter.second;
         strategies.push_back(
-        {productStrategy->getName(), productStrategy->listAudioAttributes(),
+        {productStrategy->getName(), productStrategy->listVolumeGroupAttributes(),
          productStrategy->getId()});
     }
     return NO_ERROR;
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index b036e12..f132ced 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <EngineConfig.h>
+
 #include <system/audio.h>
 
 namespace android {
@@ -25,11 +27,11 @@
 const engineConfig::ProductStrategies gOrderedStrategies = {
     {"STRATEGY_PHONE",
      {
-         {"phone", AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
+         {AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
             AUDIO_FLAG_NONE, ""}},
          },
-         {"sco", AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
+         {AUDIO_STREAM_BLUETOOTH_SCO, "AUDIO_STREAM_BLUETOOTH_SCO",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_SCO,
             ""}},
          }
@@ -37,11 +39,11 @@
     },
     {"STRATEGY_SONIFICATION",
      {
-         {"ring", AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
+         {AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
             AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          },
-         {"alarm", AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
+         {AUDIO_STREAM_ALARM, "AUDIO_STREAM_ALARM",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT,
             AUDIO_FLAG_NONE, ""}},
          }
@@ -49,7 +51,7 @@
     },
     {"STRATEGY_ENFORCED_AUDIBLE",
      {
-         {"", AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
+         {AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
             AUDIO_FLAG_AUDIBILITY_ENFORCED, ""}}
          }
@@ -57,7 +59,7 @@
     },
     {"STRATEGY_ACCESSIBILITY",
      {
-         {"", AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
+         {AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
             AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          }
@@ -65,7 +67,7 @@
     },
     {"STRATEGY_SONIFICATION_RESPECTFUL",
      {
-         {"", AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
+         {AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION, AUDIO_SOURCE_DEFAULT,
                AUDIO_FLAG_NONE, ""},
@@ -77,11 +79,11 @@
     },
     {"STRATEGY_MEDIA",
      {
-         {"assistant", AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
+         {AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
             AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          },
-         {"music", AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
+         {AUDIO_STREAM_MUSIC, "AUDIO_STREAM_MUSIC",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
                AUDIO_FLAG_NONE, ""},
@@ -95,7 +97,7 @@
                AUDIO_FLAG_NONE, ""}
           },
          },
-         {"system", AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
+         {AUDIO_STREAM_SYSTEM, "AUDIO_STREAM_SYSTEM",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_SONIFICATION,
             AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}}
          }
@@ -103,7 +105,7 @@
     },
     {"STRATEGY_DTMF",
      {
-         {"", AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
+         {AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING,
                AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}
@@ -113,7 +115,7 @@
     },
     {"STRATEGY_CALL_ASSISTANT",
      {
-         {"", AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
+         {AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
             AUDIO_FLAG_NONE, ""}}
          }
@@ -121,7 +123,7 @@
     },
     {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
      {
-         {"", AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
+         {AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
           {
               {AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
                 AUDIO_FLAG_BEACON, ""},
@@ -140,17 +142,17 @@
 const engineConfig::ProductStrategies gOrderedSystemStrategies = {
     {"rerouting",
      {
-         {"", AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
+         {AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
-            AUDIO_FLAG_NONE, ""}}
+            AUDIO_FLAG_NONE, AUDIO_TAG_APM_RESERVED_INTERNAL}}
          }
      },
     },
     {"patch",
      {
-         {"", AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
+         {AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
-            AUDIO_FLAG_NONE, ""}}
+            AUDIO_FLAG_NONE, AUDIO_TAG_APM_RESERVED_INTERNAL}}
          }
      },
     }
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index fbfcf72..1d3ad1c 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -36,16 +36,16 @@
 {
 }
 
-void ProductStrategy::addAttributes(const AudioAttributes &audioAttributes)
+void ProductStrategy::addAttributes(const VolumeGroupAttributes &volumeGroupAttributes)
 {
-    mAttributesVector.push_back(audioAttributes);
+    mAttributesVector.push_back(volumeGroupAttributes);
 }
 
-std::vector<android::AudioAttributes> ProductStrategy::listAudioAttributes() const
+std::vector<android::VolumeGroupAttributes> ProductStrategy::listVolumeGroupAttributes() const
 {
-    std::vector<android::AudioAttributes> androidAa;
+    std::vector<android::VolumeGroupAttributes> androidAa;
     for (const auto &attr : mAttributesVector) {
-        androidAa.push_back({attr.mVolumeGroup, attr.mStream, attr.mAttributes});
+        androidAa.push_back({attr.getGroupId(), attr.getStreamType(), attr.getAttributes()});
     }
     return androidAa;
 }
@@ -54,7 +54,7 @@
 {
     AttributesVector attrVector;
     for (const auto &attrGroup : mAttributesVector) {
-        attrVector.push_back(attrGroup.mAttributes);
+        attrVector.push_back(attrGroup.getAttributes());
     }
     if (not attrVector.empty()) {
         return attrVector;
@@ -62,52 +62,40 @@
     return { AUDIO_ATTRIBUTES_INITIALIZER };
 }
 
-bool ProductStrategy::matches(const audio_attributes_t attr) const
+int ProductStrategy::matchesScore(const audio_attributes_t attr) const
 {
-    return std::find_if(begin(mAttributesVector), end(mAttributesVector),
-                        [&attr](const auto &supportedAttr) {
-        return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr);
-    }) != end(mAttributesVector);
-}
-
-audio_stream_type_t ProductStrategy::getStreamTypeForAttributes(
-        const audio_attributes_t &attr) const
-{
-    const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
-                                   [&attr](const auto &supportedAttr) {
-        return AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr); });
-    if (iter == end(mAttributesVector)) {
-        return AUDIO_STREAM_DEFAULT;
+    int strategyScore = AudioProductStrategy::NO_MATCH;
+    for (const auto &attrGroup : mAttributesVector) {
+        int score = AudioProductStrategy::attributesMatchesScore(attrGroup.getAttributes(), attr);
+        if (score == AudioProductStrategy::MATCH_EQUALS) {
+            return score;
+        }
+        strategyScore = std::max(score, strategyScore);
     }
-    audio_stream_type_t streamType = iter->mStream;
-    ALOGW_IF(streamType == AUDIO_STREAM_DEFAULT,
-             "%s: Strategy %s supporting attributes %s has not stream type associated"
-             "fallback on MUSIC. Do not use stream volume API", __func__, mName.c_str(),
-             toString(attr).c_str());
-    return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
+    return strategyScore;
 }
 
 audio_attributes_t ProductStrategy::getAttributesForStreamType(audio_stream_type_t streamType) const
 {
     const auto iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
                                    [&streamType](const auto &supportedAttr) {
-        return supportedAttr.mStream == streamType; });
-    return iter != end(mAttributesVector) ? iter->mAttributes : AUDIO_ATTRIBUTES_INITIALIZER;
+        return supportedAttr.getStreamType() == streamType; });
+    return iter != end(mAttributesVector) ? iter->getAttributes() : AUDIO_ATTRIBUTES_INITIALIZER;
 }
 
 bool ProductStrategy::isDefault() const
 {
     return std::find_if(begin(mAttributesVector), end(mAttributesVector), [](const auto &attr) {
-        return attr.mAttributes == defaultAttr; }) != end(mAttributesVector);
+        return attr.getAttributes() == defaultAttr; }) != end(mAttributesVector);
 }
 
 StreamTypeVector ProductStrategy::getSupportedStreams() const
 {
     StreamTypeVector streams;
     for (const auto &supportedAttr : mAttributesVector) {
-        if (std::find(begin(streams), end(streams), supportedAttr.mStream) == end(streams) &&
-                supportedAttr.mStream != AUDIO_STREAM_DEFAULT) {
-            streams.push_back(supportedAttr.mStream);
+        if (std::find(begin(streams), end(streams), supportedAttr.getStreamType())
+                == end(streams) && supportedAttr.getStreamType() != AUDIO_STREAM_DEFAULT) {
+            streams.push_back(supportedAttr.getStreamType());
         }
     }
     return streams;
@@ -117,24 +105,14 @@
 {
     return std::find_if(begin(mAttributesVector), end(mAttributesVector),
                         [&streamType](const auto &supportedAttr) {
-        return supportedAttr.mStream == streamType; }) != end(mAttributesVector);
-}
-
-volume_group_t ProductStrategy::getVolumeGroupForAttributes(const audio_attributes_t &attr) const
-{
-    for (const auto &supportedAttr : mAttributesVector) {
-        if (AudioProductStrategy::attributesMatches(supportedAttr.mAttributes, attr)) {
-            return supportedAttr.mVolumeGroup;
-        }
-    }
-    return VOLUME_GROUP_NONE;
+        return supportedAttr.getStreamType() == streamType; }) != end(mAttributesVector);
 }
 
 volume_group_t ProductStrategy::getVolumeGroupForStreamType(audio_stream_type_t stream) const
 {
     for (const auto &supportedAttr : mAttributesVector) {
-        if (supportedAttr.mStream == stream) {
-            return supportedAttr.mVolumeGroup;
+        if (supportedAttr.getStreamType() == stream) {
+            return supportedAttr.getGroupId();
         }
     }
     return VOLUME_GROUP_NONE;
@@ -143,8 +121,10 @@
 volume_group_t ProductStrategy::getDefaultVolumeGroup() const
 {
     const auto &iter = std::find_if(begin(mAttributesVector), end(mAttributesVector),
-                                    [](const auto &attr) {return attr.mAttributes == defaultAttr;});
-    return iter != end(mAttributesVector) ? iter->mVolumeGroup : VOLUME_GROUP_NONE;
+                                    [](const auto &attr) {
+        return attr.getAttributes() == defaultAttr;
+    });
+    return iter != end(mAttributesVector) ? iter->getGroupId() : VOLUME_GROUP_NONE;
 }
 
 void ProductStrategy::dump(String8 *dst, int spaces) const
@@ -155,26 +135,32 @@
                        deviceLiteral.c_str(), mDeviceAddress.c_str());
 
     for (const auto &attr : mAttributesVector) {
-        dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.mVolumeGroup,
-                          android::toString(attr.mStream).c_str());
+        dst->appendFormat("%*sGroup: %d stream: %s\n", spaces + 3, "", attr.getGroupId(),
+                          android::toString(attr.getStreamType()).c_str());
         dst->appendFormat("%*s Attributes: ", spaces + 3, "");
-        std::string attStr =
-                attr.mAttributes == defaultAttr ? "{ Any }" : android::toString(attr.mAttributes);
+        std::string attStr = attr.getAttributes() == defaultAttr ?
+                "{ Any }" : android::toString(attr.getAttributes());
         dst->appendFormat("%s\n", attStr.c_str());
     }
 }
 
 product_strategy_t ProductStrategyMap::getProductStrategyForAttributes(
-        const audio_attributes_t &attr, bool fallbackOnDefault) const
+        const audio_attributes_t &attributes, bool fallbackOnDefault) const
 {
+    product_strategy_t bestStrategyOrdefault = PRODUCT_STRATEGY_NONE;
+    int matchScore = AudioProductStrategy::NO_MATCH;
     for (const auto &iter : *this) {
-        if (iter.second->matches(attr)) {
+        int score = iter.second->matchesScore(attributes);
+        if (score == AudioProductStrategy::MATCH_EQUALS) {
             return iter.second->getId();
         }
+        if (score > matchScore) {
+            bestStrategyOrdefault = iter.second->getId();;
+            matchScore = score;
+        }
     }
-    ALOGV("%s: No matching product strategy for attributes %s, return default", __FUNCTION__,
-          toString(attr).c_str());
-    return fallbackOnDefault? getDefault() : PRODUCT_STRATEGY_NONE;
+    return (matchScore != AudioProductStrategy::MATCH_ON_DEFAULT_SCORE || fallbackOnDefault) ?
+            bestStrategyOrdefault : PRODUCT_STRATEGY_NONE;
 }
 
 audio_attributes_t ProductStrategyMap::getAttributesForStreamType(audio_stream_type_t stream) const
@@ -190,20 +176,6 @@
     return {};
 }
 
-audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
-        const audio_attributes_t &attr) const
-{
-    for (const auto &iter : *this) {
-        audio_stream_type_t stream = iter.second->getStreamTypeForAttributes(attr);
-        if (stream != AUDIO_STREAM_DEFAULT) {
-            return stream;
-        }
-    }
-    ALOGV("%s: No product strategy for attributes %s, using default (aka MUSIC)", __FUNCTION__,
-          toString(attr).c_str());
-    return  AUDIO_STREAM_MUSIC;
-}
-
 product_strategy_t ProductStrategyMap::getDefault() const
 {
     if (mDefaultStrategy != PRODUCT_STRATEGY_NONE) {
@@ -268,16 +240,39 @@
     return at(psId)->getDeviceAddress();
 }
 
+VolumeGroupAttributes ProductStrategyMap::getVolumeGroupAttributesForAttributes(
+        const audio_attributes_t &attr, bool fallbackOnDefault) const
+{
+    int matchScore = AudioProductStrategy::NO_MATCH;
+    VolumeGroupAttributes bestVolumeGroupAttributes = {};
+    for (const auto &iter : *this) {
+        for (const auto &volGroupAttr : iter.second->getVolumeGroupAttributes()) {
+            int score = volGroupAttr.matchesScore(attr);
+            if (score == AudioProductStrategy::MATCH_EQUALS) {
+                return volGroupAttr;
+            }
+            if (score > matchScore) {
+                matchScore = score;
+                bestVolumeGroupAttributes = volGroupAttr;
+            }
+        }
+    }
+    return (matchScore != AudioProductStrategy::MATCH_ON_DEFAULT_SCORE || fallbackOnDefault) ?
+            bestVolumeGroupAttributes : VolumeGroupAttributes();
+}
+
+audio_stream_type_t ProductStrategyMap::getStreamTypeForAttributes(
+        const audio_attributes_t &attr) const
+{
+    audio_stream_type_t streamType = getVolumeGroupAttributesForAttributes(
+            attr, /* fallbackOnDefault= */ true).getStreamType();
+    return streamType != AUDIO_STREAM_DEFAULT ? streamType : AUDIO_STREAM_MUSIC;
+}
+
 volume_group_t ProductStrategyMap::getVolumeGroupForAttributes(
         const audio_attributes_t &attr, bool fallbackOnDefault) const
 {
-    for (const auto &iter : *this) {
-        volume_group_t group = iter.second->getVolumeGroupForAttributes(attr);
-        if (group != VOLUME_GROUP_NONE) {
-            return group;
-        }
-    }
-    return fallbackOnDefault ? getDefaultVolumeGroup() : VOLUME_GROUP_NONE;
+    return getVolumeGroupAttributesForAttributes(attr, fallbackOnDefault).getGroupId();
 }
 
 volume_group_t ProductStrategyMap::getVolumeGroupForStreamType(
diff --git a/services/audiopolicy/engine/common/src/VolumeGroup.cpp b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
index e189807..f5ffbba 100644
--- a/services/audiopolicy/engine/common/src/VolumeGroup.cpp
+++ b/services/audiopolicy/engine/common/src/VolumeGroup.cpp
@@ -37,6 +37,17 @@
 {
 }
 
+// Used for introspection, e.g. JAVA
+AttributesVector VolumeGroup::getSupportedAttributes() const
+{
+    AttributesVector supportedAttributes = {};
+    for (auto &aa : mGroupVolumeCurves.getAttributes()) {
+        aa.source = AUDIO_SOURCE_INVALID;
+        supportedAttributes.push_back(aa);
+    }
+    return supportedAttributes;
+}
+
 void VolumeGroup::dump(String8 *dst, int spaces) const
 {
     dst->appendFormat("\n%*s-%s (id: %d)\n", spaces, "", mName.c_str(), mId);
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 2ebb7df..119dbd6 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -16,15 +16,22 @@
 
 #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;
 struct _xmlDoc;
 
+/**
+ * AudioAttributes custom tag to identify internal strategies, whose volumes are exclusively
+ * controlled by AudioPolicyManager
+ */
+#define AUDIO_TAG_APM_RESERVED_INTERNAL "reserved_internal_strategy"
+
 namespace android {
 namespace engineConfig {
 
@@ -35,7 +42,6 @@
 using StreamVector = std::vector<audio_stream_type_t>;
 
 struct AttributesGroup {
-    std::string name;
     audio_stream_type_t stream;
     std::string volumeGroup;
     AttributesVector attributesVect;
@@ -111,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 6f560d5..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;
@@ -57,7 +140,6 @@
     static constexpr const char *collectionTag = "AttributesGroups";
 
     struct Attributes {
-        static constexpr const char *name = "name";
         static constexpr const char *streamType = "streamType";
         static constexpr const char *volumeGroup = "volumeGroup";
     };
@@ -313,12 +395,6 @@
 status_t AttributesGroupTraits::deserialize(_xmlDoc *doc, const _xmlNode *child,
                                             Collection &attributesGroup)
 {
-    std::string name = getXmlAttribute(child, Attributes::name);
-    if (name.empty()) {
-        ALOGV("AttributesGroupTraits No attribute %s found", Attributes::name);
-    }
-    ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
-
     std::string volumeGroup = getXmlAttribute(child, Attributes::volumeGroup);
     if (volumeGroup.empty()) {
         ALOGE("%s: No attribute %s found", __FUNCTION__, Attributes::volumeGroup);
@@ -339,7 +415,7 @@
     AttributesVector attributesVect;
     deserializeAttributesCollection(doc, child, attributesVect);
 
-    attributesGroup.push_back({name, streamType, volumeGroup, attributesVect});
+    attributesGroup.push_back({streamType, volumeGroup, attributesVect});
     return NO_ERROR;
 }
 
@@ -731,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 57174c7..5c37409 100644
--- a/services/audiopolicy/engine/interface/EngineInterface.h
+++ b/services/audiopolicy/engine/interface/EngineInterface.h
@@ -16,9 +16,11 @@
 
 #pragma once
 
+#include <string>
 #include <utility>
 
 #include <AudioPolicyManagerObserver.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
 #include <media/AudioProductStrategy.h>
 #include <media/AudioVolumeGroup.h>
 #include <IVolumeCurves.h>
@@ -46,6 +48,21 @@
 {
 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.
+     */
+    virtual status_t loadFromXmlConfigWithFallback(const std::string& xmlFilePath = "") = 0;
+
+    /**
      * Checks if the engine was correctly initialized.
      *
      * @return NO_ERROR if initialization has been done correctly, error code otherwise..
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/Collection.h b/services/audiopolicy/engineconfigurable/src/Collection.h
index 02b41cb..4640515 100644
--- a/services/audiopolicy/engineconfigurable/src/Collection.h
+++ b/services/audiopolicy/engineconfigurable/src/Collection.h
@@ -53,6 +53,10 @@
     {
         collectionSupported();
     }
+    ~Collection()
+    {
+        clear();
+    }
 
     /**
      * Add a policy element to the collection. Policy elements are streams, strategies, input
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index a802646..f07ce82 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -68,16 +68,21 @@
 
 Engine::Engine() : mPolicyParameterMgr(new ParameterManagerWrapper())
 {
-    status_t loadResult = loadAudioPolicyEngineConfig();
+}
+
+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);
     if (loadResult < 0) {
         ALOGE("Policy Engine configuration is invalid.");
     }
-}
-
-Engine::~Engine()
-{
-    mStreamCollection.clear();
-    mInputSourceCollection.clear();
+    return loadResult;
 }
 
 status_t Engine::initCheck()
@@ -93,7 +98,7 @@
 template <typename Key>
 Element<Key> *Engine::getFromCollection(const Key &key) const
 {
-    const Collection<Key> collection = getCollection<Key>();
+    const Collection<Key> &collection = getCollection<Key>();
     return collection.get(key);
 }
 
@@ -179,9 +184,9 @@
     return EngineBase::setDeviceConnectionState(device, state);
 }
 
-status_t Engine::loadAudioPolicyEngineConfig()
+status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
 {
-    auto result = EngineBase::loadAudioPolicyEngineConfig();
+    auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
 
     // Custom XML Parsing
     auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
@@ -401,5 +406,3 @@
 
 } // namespace audio_policy
 } // namespace android
-
-
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 001dde9..903ab34 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -33,15 +33,23 @@
 {
 public:
     Engine();
-    virtual ~Engine();
+    virtual ~Engine() = default;
 
     template <class RequestedInterface>
     RequestedInterface *queryInterface();
 
     ///
+    /// from EngineInterface
+    ///
+    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;
 
@@ -51,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,
@@ -118,7 +126,7 @@
     template <typename Property, typename Key>
     bool setPropertyForKey(const Property &property, const Key &key);
 
-    status_t loadAudioPolicyEngineConfig();
+    status_t loadAudioPolicyEngineConfig(const std::string& xmlFilePath);
 
     DeviceVector getCachedDevices(product_strategy_t ps) const;
 
@@ -136,4 +144,3 @@
 } // namespace audio_policy
 
 } // namespace android
-
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 e72249f..e2f42da 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,9 +56,18 @@
     return legacyStrategy;
 }
 
-Engine::Engine()
-{
-    auto result = EngineBase::loadAudioPolicyEngineConfig();
+status_t Engine::loadFromHalConfigWithFallback(
+        const media::audio::common::AudioHalEngineConfig& aidlConfig) {
+    return loadWithFallback(aidlConfig);
+}
+
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& 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);
@@ -70,8 +76,11 @@
     for (const auto &strategy : legacyStrategy) {
         mLegacyStrategyMap[getProductStrategyByName(strategy.name)] = strategy.id;
     }
+
+    return OK;
 }
 
+
 status_t Engine::setForceUse(audio_policy_force_use_t usage, audio_policy_forced_cfg_t config)
 {
     switch(usage) {
@@ -793,7 +802,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 be9f4cc..66225a1 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -45,8 +45,17 @@
 class Engine : public EngineBase
 {
 public:
-    Engine();
+    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:
     ///
@@ -73,9 +82,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);
 
@@ -102,4 +110,3 @@
 };
 } // namespace audio_policy
 } // namespace android
-
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 3dbb177..23d4b33 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1088,7 +1088,12 @@
     // and AudioSystem::getOutputSamplingRate().
 
     SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
-    const audio_io_handle_t output = selectOutput(outputs);
+    audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+    if (stream == AUDIO_STREAM_MUSIC &&
+        property_get_bool("audio.deep_buffer.media", false /* default_value */)) {
+        flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+    }
+    const audio_io_handle_t output = selectOutput(outputs, flags);
 
     ALOGV("getOutput() stream %d selected devices %s, output %d", stream,
           devices.toString().c_str(), output);
@@ -5608,10 +5613,12 @@
 }
 
 AudioPolicyManager::AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
+                                       EngineInstance&& engine,
                                        AudioPolicyClientInterface *clientInterface)
     :
     mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
     mConfig(config),
+    mEngine(std::move(engine)),
     mpClientInterface(clientInterface),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mA2dpSuspended(false),
@@ -5626,18 +5633,8 @@
 }
 
 status_t AudioPolicyManager::initialize() {
-    {
-        auto engLib = EngineLibrary::load(
-                        "libaudiopolicyengine" + mConfig->getEngineLibraryNameSuffix() + ".so");
-        if (!engLib) {
-            ALOGE("%s: Failed to load the engine library", __FUNCTION__);
-            return NO_INIT;
-        }
-        mEngine = engLib->createEngine();
-        if (mEngine == nullptr) {
-            ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
-            return NO_INIT;
-        }
+    if (mEngine == nullptr) {
+        return NO_INIT;
     }
     mEngine->setObserver(this);
     status_t status = mEngine->initCheck();
@@ -5713,10 +5710,14 @@
         if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
             continue;
         }
-        hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
         if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
-            ALOGW("could not open HW module %s", hwModule->getName());
-            continue;
+            if (audio_module_handle_t handle = mpClientInterface->loadHwModule(hwModule->getName());
+                    handle != AUDIO_MODULE_HANDLE_NONE) {
+                hwModule->setHandle(handle);
+            } else {
+                ALOGW("could not load HW module %s", hwModule->getName());
+                continue;
+            }
         }
         mHwModules.push_back(hwModule);
         // open all output streams needed to access attached devices.
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index a52f2c6..0de5c0e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -94,6 +94,7 @@
 
 public:
         AudioPolicyManager(const sp<const AudioPolicyConfig>& config,
+                           EngineInstance&& engine,
                            AudioPolicyClientInterface *clientInterface);
         virtual ~AudioPolicyManager();
 
@@ -360,11 +361,10 @@
         }
 
         virtual status_t getProductStrategyFromAudioAttributes(
-                const AudioAttributes &aa, product_strategy_t &productStrategy,
+                const audio_attributes_t &aa, product_strategy_t &productStrategy,
                 bool fallbackOnDefault)
         {
-            productStrategy = mEngine->getProductStrategyForAttributes(
-                    aa.getAttributes(), fallbackOnDefault);
+            productStrategy = mEngine->getProductStrategyForAttributes(aa, fallbackOnDefault);
             return (fallbackOnDefault && productStrategy == PRODUCT_STRATEGY_NONE) ?
                     BAD_VALUE : NO_ERROR;
         }
@@ -375,10 +375,9 @@
         }
 
         virtual status_t getVolumeGroupFromAudioAttributes(
-                const AudioAttributes &aa, volume_group_t &volumeGroup, bool fallbackOnDefault)
+                const audio_attributes_t &aa, volume_group_t &volumeGroup, bool fallbackOnDefault)
         {
-            volumeGroup = mEngine->getVolumeGroupForAttributes(
-                        aa.getAttributes(), fallbackOnDefault);
+            volumeGroup = mEngine->getVolumeGroupForAttributes(aa, fallbackOnDefault);
             return (fallbackOnDefault && volumeGroup == VOLUME_GROUP_NONE) ?
                     BAD_VALUE : NO_ERROR;
         }
@@ -902,6 +901,7 @@
 
         const uid_t mUidCached;                         // AID_AUDIOSERVER
         sp<const AudioPolicyConfig> mConfig;
+        EngineInstance mEngine;                         // Audio Policy Engine instance
         AudioPolicyClientInterface *mpClientInterface;  // audio policy client interface
         sp<SwAudioOutputDescriptor> mPrimaryOutput;     // primary output descriptor
         // list of descriptors for outputs currently opened
@@ -954,9 +954,6 @@
 
         uint32_t nextAudioPortGeneration();
 
-        // Audio Policy Engine Interface.
-        EngineInstance mEngine;
-
         // Surround formats that are enabled manually. Taken into account when
         // "encoded surround" is forced into "manual" mode.
         std::unordered_set<audio_format_t> mManualSurroundFormats;
diff --git a/services/audiopolicy/managerdefault/EngineLibrary.cpp b/services/audiopolicy/managerdefault/EngineLibrary.cpp
index ef699aa..ab77941 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.cpp
+++ b/services/audiopolicy/managerdefault/EngineLibrary.cpp
@@ -23,9 +23,44 @@
 
 namespace android {
 
-// static
-std::shared_ptr<EngineLibrary> EngineLibrary::load(std::string libraryPath)
+EngineInstance loadApmEngineLibraryAndCreateEngine(const std::string& librarySuffix,
+        const std::string& configXmlFilePath)
 {
+    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->createEngineUsingXmlConfig(configXmlFilePath);
+    if (engine == nullptr) {
+        ALOGE("%s: Failed to instantiate the APM engine", __func__);
+        return nullptr;
+    }
+    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)
+{
+    std::string libraryPath = "libaudiopolicyengine" + librarySuffix + ".so";
     std::shared_ptr<EngineLibrary> engLib(new EngineLibrary());
     return engLib->init(std::move(libraryPath)) ? engLib : nullptr;
 }
@@ -35,6 +70,36 @@
     close();
 }
 
+EngineInstance EngineLibrary::createEngineUsingXmlConfig(const std::string& xmlFilePath)
+{
+    auto instance = createEngine();
+    if (instance != nullptr) {
+        if (status_t status = instance->loadFromXmlConfigWithFallback(xmlFilePath);
+                status == OK) {
+            return instance;
+        } else {
+            ALOGE("%s: loading of the engine config with XML configuration file \"%s\" failed: %d",
+                    __func__, xmlFilePath.empty() ? "default" : xmlFilePath.c_str(), status);
+        }
+    }
+    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 f143916..4710e34 100644
--- a/services/audiopolicy/managerdefault/EngineLibrary.h
+++ b/services/audiopolicy/managerdefault/EngineLibrary.h
@@ -21,14 +21,20 @@
 #include <string>
 
 #include <EngineInterface.h>
+#include <android/media/audio/common/AudioHalEngineConfig.h>
 
 namespace android {
 
 using EngineInstance = std::unique_ptr<EngineInterface, std::function<void (EngineInterface*)>>;
 
+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:
-    static std::shared_ptr<EngineLibrary> load(std::string libraryPath);
+    static std::shared_ptr<EngineLibrary> load(const std::string& librarySuffix);
     ~EngineLibrary();
 
     EngineLibrary(const EngineLibrary&) = delete;
@@ -36,11 +42,14 @@
     EngineLibrary& operator=(const EngineLibrary&) = delete;
     EngineLibrary& operator=(EngineLibrary&&) = delete;
 
-    EngineInstance createEngine();
+    EngineInstance createEngineUsingXmlConfig(const std::string& xmlFilePath);
+    EngineInstance createEngineUsingHalConfig(
+            const media::audio::common::AudioHalEngineConfig& config);
 
 private:
     EngineLibrary() = default;
     bool init(std::string libraryPath);
+    EngineInstance createEngine();
     void close();
 
     void *mLibraryHandle = nullptr;
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 8c541f6..734bf9e 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -35,6 +35,7 @@
         "libaudiofoundation",
         "libaudiohal",
         "libaudiopolicy",
+        "libaudiopolicycomponents",
         "libaudiopolicymanagerdefault",
         "libaudioutils",
         "libbinder",
@@ -65,7 +66,6 @@
     ],
 
     static_libs: [
-        "libaudiopolicycomponents",
         "framework-permission-aidl-cpp",
     ],
 
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 4691135..290db97 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -27,6 +27,18 @@
 
 /* implementation of the client interface from the policy manager */
 
+status_t AudioPolicyService::AudioPolicyClient::getAudioPolicyConfig(
+        media::AudioPolicyConfig *config)
+{
+    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+    if (af == 0) {
+        ALOGW("%s: could not get AudioFlinger", __func__);
+        return AUDIO_MODULE_HANDLE_NONE;
+    }
+
+    return af->getAudioPolicyConfig(config);
+}
+
 audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
 {
     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index b111865..70a1785 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -924,8 +924,7 @@
         for (auto& stream : processingChain) {
             auto effectDescs = std::make_unique<EffectDescVector>();
             for (auto& effect : stream.effects) {
-                effectDescs->mEffects.add(
-                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+                effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
             }
             streams.add(stream.type, effectDescs.release());
         }
@@ -935,8 +934,7 @@
         for (auto& deviceProcess : processingChain) {
             auto effectDescs = std::make_unique<EffectDescVector>();
             for (auto& effect : deviceProcess.effects) {
-                effectDescs->mEffects.add(
-                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+                effectDescs->mEffects.add(new EffectDesc{effect->name.c_str(), effect->uuid});
             }
             auto deviceEffects = std::make_unique<DeviceEffects>(
                         std::move(effectDescs), deviceProcess.type, deviceProcess.address);
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 0df3962..91857f9 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -317,7 +317,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,
@@ -326,7 +326,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;
@@ -554,7 +554,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,
@@ -564,7 +564,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(
@@ -1026,10 +1026,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));
@@ -1049,10 +1049,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;
@@ -1071,9 +1071,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")));
@@ -1090,9 +1090,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")));
@@ -1130,12 +1130,13 @@
     return Status::ok();
 }
 
-Status AudioPolicyService::getDevicesForAttributes(const media::AudioAttributesEx& attrAidl,
-                                                   bool forVolume,
-                                                   std::vector<AudioDevice>* _aidl_return)
+Status AudioPolicyService::getDevicesForAttributes(
+        const media::audio::common::AudioAttributes& attrAidl,
+        bool forVolume,
+        std::vector<AudioDevice>* _aidl_return)
 {
-    AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesEx_AudioAttributes(attrAidl));
+    audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
+            aidl2legacy_AudioAttributes_audio_attributes_t(attrAidl));
     AudioDeviceTypeAddrVector devices;
 
     if (mAudioPolicyManager == NULL) {
@@ -1144,8 +1145,7 @@
     Mutex::Autolock _l(mLock);
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
-            mAudioPolicyManager->getDevicesForAttributes(
-                    aa.getAttributes(), &devices, forVolume)));
+            mAudioPolicyManager->getDevicesForAttributes(aa, &devices, forVolume)));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(
             convertContainer<std::vector<AudioDevice>>(devices,
                                                        legacy2aidl_AudioDeviceTypeAddress));
@@ -1461,12 +1461,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")));
 
@@ -1783,12 +1783,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)));
@@ -2050,9 +2050,10 @@
 }
 
 Status AudioPolicyService::getProductStrategyFromAudioAttributes(
-        const media::AudioAttributesEx& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) {
-    AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesEx_AudioAttributes(aaAidl));
+        const media::audio::common::AudioAttributes& aaAidl,
+        bool fallbackOnDefault, int32_t* _aidl_return) {
+    audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
+            aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl));
     product_strategy_t productStrategy;
 
     if (mAudioPolicyManager == NULL) {
@@ -2083,9 +2084,10 @@
 }
 
 Status AudioPolicyService::getVolumeGroupFromAudioAttributes(
-        const media::AudioAttributesEx& aaAidl, bool fallbackOnDefault, int32_t* _aidl_return) {
-    AudioAttributes aa = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioAttributesEx_AudioAttributes(aaAidl));
+        const media::audio::common::AudioAttributes& aaAidl,
+        bool fallbackOnDefault, int32_t* _aidl_return) {
+    audio_attributes_t aa = VALUE_OR_RETURN_BINDER_STATUS(
+            aidl2legacy_AudioAttributes_audio_attributes_t(aaAidl));
     volume_group_t volumeGroup;
 
     if (mAudioPolicyManager == NULL) {
@@ -2299,7 +2301,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) {
@@ -2309,7 +2311,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()) {
@@ -2326,9 +2328,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);
     }
@@ -2336,7 +2339,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);
@@ -2347,13 +2350,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);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index b343f34..50c2c46 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -180,8 +180,23 @@
 
 static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
 {
-    AudioPolicyManager *apm = new AudioPolicyManager(
-            AudioPolicyConfig::loadFromApmXmlConfigWithFallback(), 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 a101309..8c85bff 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -69,7 +69,7 @@
     public IBinder::DeathRecipient,
     public SpatializerPolicyCallback
 {
-    friend class BinderService<AudioPolicyService>;
+    friend class sp<AudioPolicyService>;
 
 public:
     // for BinderService
@@ -97,7 +97,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,
@@ -105,7 +106,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,
@@ -122,19 +123,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::AudioAttributesEx& 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,
@@ -169,7 +170,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,
@@ -200,7 +201,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;
@@ -226,14 +227,16 @@
     binder::Status isUltrasoundSupported(bool* _aidl_return) override;
     binder::Status listAudioProductStrategies(
             std::vector<media::AudioProductStrategy>* _aidl_return) override;
-    binder::Status getProductStrategyFromAudioAttributes(const media::AudioAttributesEx& 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::AudioAttributesEx& 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(
@@ -267,16 +270,16 @@
     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;
 
     status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
@@ -707,6 +710,8 @@
         explicit AudioPolicyClient(AudioPolicyService *service) : mAudioPolicyService(service) {}
         virtual ~AudioPolicyClient() {}
 
+        virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig *config);
+
         //
         // Audio HW module functions
         //
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 8499c1c..b9ee8dd 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -74,6 +74,7 @@
         "libaudioclient",
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
+        "libaudiopolicycomponents",
         "libaudiopolicymanagerdefault",
         "libcutils",
         "liblog",
@@ -85,8 +86,6 @@
         "libxml2",
     ],
 
-    static_libs: ["libaudiopolicycomponents"],
-
     header_libs: [
         "libaudiopolicyengine_interface_headers",
         "libaudiopolicymanager_interface_headers",
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index e81a3b5..b212a32 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -25,6 +25,9 @@
     virtual ~AudioPolicyTestClient() = default;
 
     // AudioPolicyClientInterface Implementation
+    status_t getAudioPolicyConfig(media::AudioPolicyConfig* /*config*/) override {
+        return INVALID_OPERATION;
+    }
     audio_module_handle_t loadHwModule(const char* /*name*/) override {
         return AUDIO_MODULE_HANDLE_NONE;
     }
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 9ad9849..31ee252 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -22,10 +22,12 @@
 class AudioPolicyTestManager : public AudioPolicyManager {
   public:
     explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
-            : AudioPolicyManager(AudioPolicyConfig::createDefault(), clientInterface) {}
+            : AudioPolicyTestManager(AudioPolicyConfig::createDefault(), clientInterface) {}
     AudioPolicyTestManager(const sp<const AudioPolicyConfig>& config,
             AudioPolicyClientInterface *clientInterface)
-            : AudioPolicyManager(config, clientInterface) {}
+            : AudioPolicyManager(config,
+                    loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+                    clientInterface) {}
     using AudioPolicyManager::getConfig;
     using AudioPolicyManager::initialize;
     using AudioPolicyManager::getOutputs;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index c72986d..4259efd 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -2292,7 +2292,11 @@
         const CameraResourceCost& resourceCost,
         sp<ProviderInfo> parentProvider,
         const std::vector<std::string>& publicCameraIds) :
-        DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
+        DeviceInfo(name, tagId, id,
+                   hardware::hidl_version{
+                        static_cast<uint16_t >(
+                                parentProvider->getIPCTransport() == IPCTransport::HIDL ? 3 : 1),
+                                minorVersion},
                    publicCameraIds, resourceCost, parentProvider) { }
 
 void CameraProviderManager::ProviderInfo::DeviceInfo3::notifyDeviceStateChange(int64_t newState) {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
index e43b91f..4986199 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/Android.bp
@@ -29,11 +29,8 @@
     ],
 }
 
-cc_fuzz {
-    name: "camera_service_fuzzer",
-    srcs: [
-        "camera_service_fuzzer.cpp",
-    ],
+cc_defaults {
+    name: "camera_service_fuzzer_defaults",
     header_libs: [
         "libmedia_headers",
     ],
@@ -73,3 +70,28 @@
 
     },
 }
+
+cc_fuzz {
+    name: "camera_service_fuzzer",
+    srcs: [
+        "camera_service_fuzzer.cpp",
+    ],
+    defaults: [
+        "camera_service_fuzzer_defaults"
+    ],
+}
+
+cc_fuzz {
+    name: "camera_service_aidl_fuzzer",
+    srcs: [
+        "camera_service_aidl_fuzzer.cpp",
+    ],
+    defaults: [
+        "camera_service_fuzzer_defaults",
+        "service_fuzzer_defaults",
+        "fuzzer_disable_leaks",
+    ],
+    fuzz_config: {
+        triage_assignee: "waghpawan@google.com",
+    },
+}
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp
new file mode 100644
index 0000000..a0fb93c
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_aidl_fuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 <fuzzbinder/libbinder_driver.h>
+#include <CameraService.h>
+
+using android::fuzzService;
+using android::sp;
+using android::CameraService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto service = sp<CameraService>::make();
+    fuzzService(service, FuzzedDataProvider(data, size));
+    return 0;
+}
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index acafe56..e22d749 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -89,3 +89,25 @@
         "code_coverage.policy",
     ],
 }
+
+cc_fuzz {
+    name: "mediaextractor_service_fuzzer",
+    shared_libs: [
+        "libmedia",
+        "libmediaextractorservice",
+        "libmediautils",
+        "liblog",
+        "libavservices_minijail",
+    ],
+    defaults: [
+        "service_fuzzer_defaults",
+        "fuzzer_disable_leaks",
+    ],
+    srcs: ["fuzzers/MediaExtractorServiceFuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "android-media-playback+bugs@google.com",
+        ],
+        triage_assignee: "waghpawan@google.com",
+    },
+}
\ No newline at end of file
diff --git a/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
new file mode 100644
index 0000000..d329e54
--- /dev/null
+++ b/services/mediaextractor/fuzzers/MediaExtractorServiceFuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include "MediaExtractorService.h"
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaExtractorService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto service = sp<MediaExtractorService>::make();
+    fuzzService(service, FuzzedDataProvider(data, size));
+    return 0;
+}
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 20a6378..99703e3 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -27,13 +27,8 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
-cc_fuzz {
-    name: "mediametrics_service_fuzzer",
-
-    srcs: [
-        "mediametrics_service_fuzzer.cpp",
-    ],
-
+cc_defaults {
+    name: "mediametrics_service_fuzzer_defaults",
     static_libs: [
         "libmediametrics",
         "libmediametricsservice",
@@ -78,3 +73,26 @@
         fuzzed_code_usage: "shipped",
     },
 }
+
+cc_fuzz {
+    name: "mediametrics_service_fuzzer",
+
+    srcs: [
+        "mediametrics_service_fuzzer.cpp",
+    ],
+    defaults: [
+        "mediametrics_service_fuzzer_defaults",
+    ],
+}
+
+cc_fuzz {
+    name: "mediametrics_aidl_fuzzer",
+    srcs: [
+        "mediametrics_aidl_fuzzer.cpp",
+    ],
+    defaults: [
+        "service_fuzzer_defaults",
+        "fuzzer_disable_leaks",
+        "mediametrics_service_fuzzer_defaults",
+    ],
+}
diff --git a/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
new file mode 100644
index 0000000..c7468c7
--- /dev/null
+++ b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+#include <fuzzbinder/libbinder_driver.h>
+
+#include <mediametricsservice/MediaMetricsService.h>
+
+using ::android::fuzzService;
+using ::android::sp;
+using ::android::MediaMetricsService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto service = sp<MediaMetricsService>::make();
+    fuzzService(service, FuzzedDataProvider(data, size));
+    return 0;
+}