[automerger skipped] Merge changes I482c2a73,Id81f03fa,I55264110 into android15-tests-dev am: 0826325e0e -s ours

am skip reason: Merged-In I482c2a731f95b7f8e9c3e4ed4ce7ac4d0aae94df with SHA-1 9dbb416f7d is already in history

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

Change-Id: I4d47df33752e5cfdf10162a8fbd74298f1c4f1ed
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/camera/Android.bp b/camera/Android.bp
index 9e1efae..b6241f4 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -54,7 +54,13 @@
 cc_aconfig_library {
     name: "camera_platform_flags_c_lib",
     aconfig_declarations: "camera_platform_flags",
+}
+
+cc_aconfig_library {
+    name: "camera_platform_flags_c_lib_for_test",
+    aconfig_declarations: "camera_platform_flags",
     host_supported: true,
+    mode: "test",
 }
 
 java_aconfig_library {
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index f36a743..0c80e7e 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -177,14 +177,11 @@
 
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder;
-        do {
-            binder = sm->getService(toString16(kCameraServiceName));
-            if (binder != nullptr) {
-                break;
-            }
-            ALOGW("CameraService not published, waiting...");
-            usleep(kCameraServicePollDelay);
-        } while(true);
+        binder = sm->checkService(String16(kCameraServiceName));
+        if (binder == nullptr) {
+            ALOGE("%s: Could not get CameraService instance.", __FUNCTION__);
+            return nullptr;
+        }
         if (mDeathNotifier == nullptr) {
             mDeathNotifier = new DeathNotifier(this);
         }
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index d8bf6b1..f4124ef 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -99,7 +99,6 @@
 
   private:
     sp<hardware::ICameraService> mCameraService;
-    const int                    kCameraServicePollDelay = 500000; // 0.5s
     const char*                  kCameraServiceName      = "media.camera";
     Mutex                        mLock;
 
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index 9a06bd2..cce6338 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -11,13 +11,13 @@
     name: "aidl_clearkey_service_defaults-use-shared-deps",
 
     shared_libs: [
+        "android.hardware.drm-V1-ndk",
         "libbase",
         "libbinder_ndk",
         "libcrypto",
         "liblog",
         "libprotobuf-cpp-lite",
         "libutils",
-        "android.hardware.drm-V1-ndk",
     ],
 
     static_libs: [
@@ -62,7 +62,11 @@
 
     relative_install_path: "hw",
 
-    cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wthread-safety",
+    ],
 
     include_dirs: ["frameworks/av/include"],
 
@@ -81,7 +85,7 @@
     ],
     srcs: ["Service.cpp"],
     init_rc: ["android.hardware.drm-service.clearkey.rc"],
-    vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
+    vintf_fragment_modules: ["android.hardware.drm-service.clearkey.xml_vintf"],
 }
 
 cc_binary {
@@ -93,7 +97,13 @@
     overrides: ["android.hardware.drm-service.clearkey"],
     srcs: ["ServiceLazy.cpp"],
     init_rc: ["android.hardware.drm-service-lazy.clearkey.rc"],
-    vintf_fragments: ["android.hardware.drm-service.clearkey.xml"],
+    vintf_fragment_modules: ["android.hardware.drm-service.clearkey.xml_vintf"],
+}
+
+vintf_fragment {
+    name: "android.hardware.drm-service.clearkey.xml_vintf",
+    src: "android.hardware.drm-service.clearkey.xml",
+    vendor: true,
 }
 
 cc_binary {
@@ -137,18 +147,22 @@
 
     relative_install_path: "hw",
 
-    cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wthread-safety",
+    ],
 
     include_dirs: ["frameworks/av/include"],
 
     shared_libs: [
+        "android.hardware.drm-V1-ndk",
         "libbase",
         "libbinder_ndk",
         "libcrypto",
         "liblog",
         "libprotobuf-cpp-lite",
         "libutils",
-        "android.hardware.drm-V1-ndk",
     ],
 
     static_libs: [
@@ -192,7 +206,7 @@
     ],
     prebuilts: [
         "android.hardware.drm-service.clearkey.apex.rc",
-        "android.hardware.drm-service.clearkey.xml"
+        "android.hardware.drm-service.clearkey.xml",
     ],
     overrides: [
         "android.hardware.drm-service.clearkey",
@@ -233,11 +247,11 @@
     ],
     prebuilts: [
         "android.hardware.drm-service-lazy.clearkey.apex.rc",
-        "android.hardware.drm-service.clearkey.xml"
+        "android.hardware.drm-service.clearkey.xml",
     ],
     overrides: [
-        "android.hardware.drm-service.clearkey",
         "android.hardware.drm-service-lazy.clearkey",
+        "android.hardware.drm-service.clearkey",
         "com.android.hardware.drm.clearkey",
     ],
 }
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
index 31cb7c0..8a93132 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -37,7 +37,6 @@
 const int kSecureStopIdStart = 100;
 const std::string kOfflineLicense("\"type\":\"persistent-license\"");
 const std::string kStreaming("Streaming");
-const std::string kTemporaryLicense("\"type\":\"temporary\"");
 const std::string kTrue("True");
 
 const std::string kQueryKeyLicenseType("LicenseType");
diff --git a/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp b/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp
index ddbc594..cd129ac 100644
--- a/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp
+++ b/drm/mediadrm/plugins/clearkey/common/JsonWebKey.cpp
@@ -27,10 +27,7 @@
 const std::string kKeyTypeTag("kty");
 const std::string kKeyTag("k");
 const std::string kKeyIdTag("kid");
-const std::string kMediaSessionType("type");
-const std::string kPersistentLicenseSession("persistent-license");
 const std::string kSymmetricKeyValue("oct");
-const std::string kTemporaryLicenseSession("temporary");
 }  // namespace
 
 namespace clearkeydrm {
diff --git a/media/aconfig/codec_fwk.aconfig b/media/aconfig/codec_fwk.aconfig
index d662585..2bf53f9 100644
--- a/media/aconfig/codec_fwk.aconfig
+++ b/media/aconfig/codec_fwk.aconfig
@@ -13,6 +13,16 @@
 }
 
 flag {
+  name: "dataspace_v0_partial"
+  namespace: "codec_fwk"
+  description: "Bugfix flag for using V0 dataspace in some cases"
+  bug: "313827126"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "dynamic_color_aspects"
   is_exported: true
   namespace: "codec_fwk"
@@ -98,6 +108,16 @@
 }
 
 flag {
+  name: "secure_codecs_require_crypto"
+  namespace: "codec_fwk"
+  description: "Bugfix flag for requiring setting crypto for secure codecs"
+  bug: "365162324"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
+
+flag {
   name: "set_callback_stall"
   namespace: "codec_fwk"
   description: "Bugfix flag for setCallback stall"
@@ -133,3 +153,10 @@
   description: "Feature flag to track teamfood population"
   bug: "328770262"
 }
+
+flag {
+  name: "thumbnail_block_model"
+  namespace: "codec_fwk"
+  description: "Feature flag for using block model decoder in thumbnail generation"
+  bug: "329521645"
+}
diff --git a/media/audio/aconfig/Android.bp b/media/audio/aconfig/Android.bp
index de8aca7..a5aeff2 100644
--- a/media/audio/aconfig/Android.bp
+++ b/media/audio/aconfig/Android.bp
@@ -50,6 +50,23 @@
 }
 
 cc_aconfig_library {
+    name: "com.android.media.audioserver-aconfig-cc-ro",
+    aconfig_declarations: "com.android.media.audioserver-aconfig",
+    defaults: ["audio-aconfig-cc-defaults"],
+    double_loadable: true,
+    host_supported: true,
+    product_available: true,
+    vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
+    min_sdk_version: "29",
+    mode: "force-read-only",
+}
+
+cc_aconfig_library {
     name: "com.android.media.audio-aconfig-cc",
     aconfig_declarations: "com.android.media.audio-aconfig",
     defaults: ["audio-aconfig-cc-defaults"],
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
index 9eaddce..01b6e42 100644
--- a/media/audioaidlconversion/AidlConversionCppNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -76,6 +76,8 @@
 using media::audio::common::AudioOffloadInfo;
 using media::audio::common::AudioOutputFlags;
 using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPolicyForcedConfig;
+using media::audio::common::AudioPolicyForceUse;
 using media::audio::common::AudioPort;
 using media::audio::common::AudioPortConfig;
 using media::audio::common::AudioPortDeviceExt;
@@ -3301,6 +3303,138 @@
     return OK;
 }
 
+ConversionResult<audio_policy_force_use_t>
+aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(AudioPolicyForceUse aidl) {
+    switch (aidl) {
+        case AudioPolicyForceUse::COMMUNICATION:
+            return AUDIO_POLICY_FORCE_FOR_COMMUNICATION;
+        case AudioPolicyForceUse::MEDIA:
+            return AUDIO_POLICY_FORCE_FOR_MEDIA;
+        case AudioPolicyForceUse::RECORD:
+            return AUDIO_POLICY_FORCE_FOR_RECORD;
+        case AudioPolicyForceUse::DOCK:
+            return AUDIO_POLICY_FORCE_FOR_DOCK;
+        case AudioPolicyForceUse::SYSTEM:
+            return AUDIO_POLICY_FORCE_FOR_SYSTEM;
+        case AudioPolicyForceUse::HDMI_SYSTEM_AUDIO:
+            return AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO;
+        case AudioPolicyForceUse::ENCODED_SURROUND:
+            return AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND;
+        case AudioPolicyForceUse::VIBRATE_RINGING:
+            return AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPolicyForceUse>
+legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy) {
+    switch (legacy) {
+        case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
+            return AudioPolicyForceUse::COMMUNICATION;
+        case AUDIO_POLICY_FORCE_FOR_MEDIA:
+            return AudioPolicyForceUse::MEDIA;
+        case AUDIO_POLICY_FORCE_FOR_RECORD:
+            return AudioPolicyForceUse::RECORD;
+        case AUDIO_POLICY_FORCE_FOR_DOCK:
+            return AudioPolicyForceUse::DOCK;
+        case AUDIO_POLICY_FORCE_FOR_SYSTEM:
+            return AudioPolicyForceUse::SYSTEM;
+        case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
+            return AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
+        case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
+            return AudioPolicyForceUse::ENCODED_SURROUND;
+        case AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:
+            return AudioPolicyForceUse::VIBRATE_RINGING;
+        case AUDIO_POLICY_FORCE_USE_CNT:
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_policy_forced_cfg_t>
+aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(AudioPolicyForcedConfig aidl) {
+    switch (aidl) {
+        case AudioPolicyForcedConfig::NONE:
+            return AUDIO_POLICY_FORCE_NONE;
+        case AudioPolicyForcedConfig::SPEAKER:
+            return AUDIO_POLICY_FORCE_SPEAKER;
+        case AudioPolicyForcedConfig::HEADPHONES:
+            return AUDIO_POLICY_FORCE_HEADPHONES;
+        case AudioPolicyForcedConfig::BT_SCO:
+            return AUDIO_POLICY_FORCE_BT_SCO;
+        case AudioPolicyForcedConfig::BT_A2DP:
+            return AUDIO_POLICY_FORCE_BT_A2DP;
+        case AudioPolicyForcedConfig::WIRED_ACCESSORY:
+            return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
+        case AudioPolicyForcedConfig::BT_CAR_DOCK:
+            return AUDIO_POLICY_FORCE_BT_CAR_DOCK;
+        case AudioPolicyForcedConfig::BT_DESK_DOCK:
+            return AUDIO_POLICY_FORCE_BT_DESK_DOCK;
+        case AudioPolicyForcedConfig::ANALOG_DOCK:
+            return AUDIO_POLICY_FORCE_ANALOG_DOCK;
+        case AudioPolicyForcedConfig::DIGITAL_DOCK:
+            return AUDIO_POLICY_FORCE_DIGITAL_DOCK;
+        case AudioPolicyForcedConfig::NO_BT_A2DP:
+            return AUDIO_POLICY_FORCE_NO_BT_A2DP;
+        case AudioPolicyForcedConfig::SYSTEM_ENFORCED:
+            return AUDIO_POLICY_FORCE_SYSTEM_ENFORCED;
+        case AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED:
+            return AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED;
+        case AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER:
+            return AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER;
+        case AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS:
+            return AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS;
+        case AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL:
+            return AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL;
+        case AudioPolicyForcedConfig::BT_BLE:
+            return AUDIO_POLICY_FORCE_BT_BLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPolicyForcedConfig>
+legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy) {
+    switch (legacy) {
+        case AUDIO_POLICY_FORCE_NONE:
+            return AudioPolicyForcedConfig::NONE;
+        case AUDIO_POLICY_FORCE_SPEAKER:
+            return AudioPolicyForcedConfig::SPEAKER;
+        case AUDIO_POLICY_FORCE_HEADPHONES:
+            return AudioPolicyForcedConfig::HEADPHONES;
+        case AUDIO_POLICY_FORCE_BT_SCO:
+            return AudioPolicyForcedConfig::BT_SCO;
+        case AUDIO_POLICY_FORCE_BT_A2DP:
+            return AudioPolicyForcedConfig::BT_A2DP;
+        case AUDIO_POLICY_FORCE_WIRED_ACCESSORY:
+            return AudioPolicyForcedConfig::WIRED_ACCESSORY;
+        case AUDIO_POLICY_FORCE_BT_CAR_DOCK:
+            return AudioPolicyForcedConfig::BT_CAR_DOCK;
+        case AUDIO_POLICY_FORCE_BT_DESK_DOCK:
+            return AudioPolicyForcedConfig::BT_DESK_DOCK;
+        case AUDIO_POLICY_FORCE_ANALOG_DOCK:
+            return AudioPolicyForcedConfig::ANALOG_DOCK;
+        case AUDIO_POLICY_FORCE_DIGITAL_DOCK:
+            return AudioPolicyForcedConfig::DIGITAL_DOCK;
+        case AUDIO_POLICY_FORCE_NO_BT_A2DP:
+            return AudioPolicyForcedConfig::NO_BT_A2DP;
+        case AUDIO_POLICY_FORCE_SYSTEM_ENFORCED:
+            return AudioPolicyForcedConfig::SYSTEM_ENFORCED;
+        case AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED:
+            return AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED;
+        case AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER:
+            return AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER;
+        case AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS:
+            return AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS;
+        case AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL:
+            return AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL;
+        case AUDIO_POLICY_FORCE_BT_BLE:
+            return AudioPolicyForcedConfig::BT_BLE;
+        case AUDIO_POLICY_FORCE_CFG_CNT:
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
 }  // namespace android
 
 #undef GET_DEVICE_DESC_CONNECTION
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
index 9b14a5e..5f7260d 100644
--- a/media/audioaidlconversion/AidlConversionNdk.cpp
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -35,6 +35,7 @@
 
 using hardware::audio::common::PlaybackTrackMetadata;
 using hardware::audio::common::RecordTrackMetadata;
+using hardware::audio::common::SourceMetadata;
 using ::android::BAD_VALUE;
 using ::android::OK;
 
@@ -194,5 +195,17 @@
     return aidl;
 }
 
+// static
+ConversionResult<SourceMetadata>
+legacy2aidl_playback_track_metadata_v7_SourceMetadata(
+        const std::vector<playback_track_metadata_v7_t>& legacy) {
+    SourceMetadata aidl;
+    aidl.tracks = VALUE_OR_RETURN(
+            convertContainer<std::vector<PlaybackTrackMetadata>>(
+                    legacy,
+                    legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
+    return aidl;
+}
+
 }  // namespace android
 }  // aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
index 7268464..9dfb7e7 100644
--- a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -58,6 +58,8 @@
 #include PREFIX(android/media/audio/common/AudioMode.h)
 #include PREFIX(android/media/audio/common/AudioOffloadInfo.h)
 #include PREFIX(android/media/audio/common/AudioOutputFlags.h)
+#include PREFIX(android/media/audio/common/AudioPolicyForceUse.h)
+#include PREFIX(android/media/audio/common/AudioPolicyForcedConfig.h)
 #include PREFIX(android/media/audio/common/AudioPort.h)
 #include PREFIX(android/media/audio/common/AudioPortConfig.h)
 #include PREFIX(android/media/audio/common/AudioPortExt.h)
@@ -76,6 +78,7 @@
 
 #include <system/audio.h>
 #include <system/audio_effect.h>
+#include <system/audio_policy.h>
 
 #if defined(BACKEND_NDK_IMPL)
 namespace aidl {
@@ -454,6 +457,18 @@
         media::audio::common::MicrophoneInfo* aidlInfo,
         media::audio::common::MicrophoneDynamicInfo* aidlDynamic);
 
+ConversionResult<audio_policy_forced_cfg_t>
+aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(
+        media::audio::common::AudioPolicyForcedConfig aidl);
+ConversionResult<media::audio::common::AudioPolicyForcedConfig>
+legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy);
+
+ConversionResult<audio_policy_force_use_t>
+aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+        media::audio::common::AudioPolicyForceUse aidl);
+ConversionResult<media::audio::common::AudioPolicyForceUse>
+legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy);
+
 }  // namespace android
 
 #if defined(BACKEND_NDK_IMPL)
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
index 813a728..b8a3110 100644
--- a/media/audioaidlconversion/include/media/AidlConversionNdk.h
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -28,6 +28,7 @@
 
 #include <aidl/android/hardware/audio/common/PlaybackTrackMetadata.h>
 #include <aidl/android/hardware/audio/common/RecordTrackMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
 #include <aidl/android/media/audio/common/AudioConfig.h>
 #include <media/AidlConversionUtil.h>
 
@@ -56,5 +57,9 @@
 ConversionResult<hardware::audio::common::RecordTrackMetadata>
 legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy);
 
+ConversionResult<hardware::audio::common::SourceMetadata>
+legacy2aidl_playback_track_metadata_v7_SourceMetadata(
+        const std::vector<playback_track_metadata_v7_t>& legacy);
+
 }  // namespace android
 }  // namespace aidl
diff --git a/media/audioserver/Android.bp b/media/audioserver/Android.bp
index ac2fcbe..47b48e3 100644
--- a/media/audioserver/Android.bp
+++ b/media/audioserver/Android.bp
@@ -20,13 +20,6 @@
         "-Werror",
     ],
 
-    header_libs: [
-        "audiopolicyservicelocal_headers",
-        "libaudiohal_headers",
-        "libmedia_headers",
-        "libmediametrics_headers",
-    ],
-
     defaults: [
         "latest_android_hardware_audio_core_sounddose_ndk_shared",
         "latest_android_media_audio_common_types_cpp_shared",
@@ -40,39 +33,10 @@
         "libaudioflinger",
         "libaudiopolicyservice",
         "libmedialogservice",
-        "libnbaio",
     ],
 
     shared_libs: [
-        "libaudioclient",
-        "libaudioprocessing",
-        "libbinder",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libmedia",
-        "libmediautils",
-        "libnblog",
-        "libpowermanager",
-        "libutils",
-        "libvibrator",
-    ],
-
-    // TODO check if we still need all of these include directories
-    include_dirs: [
-        "external/sonic",
-        "frameworks/av/media/libaaudio/include",
-        "frameworks/av/media/libaaudio/src",
-        "frameworks/av/media/libaaudio/src/binding",
-        "frameworks/av/services/audioflinger",
-        "frameworks/av/services/audiopolicy",
-        "frameworks/av/services/audiopolicy/common/include",
-        "frameworks/av/services/audiopolicy/common/managerdefinitions/include",
-        "frameworks/av/services/audiopolicy/engine/interface",
-        "frameworks/av/services/audiopolicy/service",
-        "frameworks/av/services/medialog",
-        "frameworks/av/services/oboeservice", // TODO oboeservice is the old folder name for aaudioservice. It will be changed.
-
+        "libhidlbase", // required for threadpool config.
     ],
 
     init_rc: ["audioserver.rc"],
diff --git a/media/codec2/hal/aidl/ComponentStore.cpp b/media/codec2/hal/aidl/ComponentStore.cpp
index ea4d045..de9332b 100644
--- a/media/codec2/hal/aidl/ComponentStore.cpp
+++ b/media/codec2/hal/aidl/ComponentStore.cpp
@@ -153,6 +153,13 @@
         mParamReflectors.push_back(paramReflector);
     }
 #endif
+    // MultiAccessUnit reflector helper is allocated once per store.
+    // All components in this store can reuse this reflector helper.
+    if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+        std::shared_ptr<C2ReflectorHelper> helper = std::make_shared<C2ReflectorHelper>();
+        mParamReflectors.push_back(helper);
+        mMultiAccessUnitReflector = helper;
+    }
 
     // Retrieve supported parameters from store
     using namespace std::placeholders;
@@ -212,12 +219,20 @@
     if (c2interface == nullptr) {
         return nullptr;
     }
+    // Framework support for Large audio frame feature depends on:
+    // 1. All feature flags enabled on platform
+    // 2. The capability of the implementation to use the same input buffer
+    //    for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+    // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
     if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
         c2_status_t err = C2_OK;
         C2ComponentDomainSetting domain;
         std::vector<std::unique_ptr<C2Param>> heapParams;
-        err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
-        if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+        C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+        err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+        if (err == C2_OK
+                && (domain.value == C2Component::DOMAIN_AUDIO)
+                && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
             std::vector<std::shared_ptr<C2ParamDescriptor>> params;
             bool isComponentSupportsLargeAudioFrame = false;
             c2interface->querySupportedParams_nb(&params);
@@ -234,7 +249,7 @@
                 // thus we pass the component's param reflector, which is mParamReflectors[0].
                 multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
                         c2interface,
-                        std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+                        mMultiAccessUnitReflector);
             }
         }
     }
diff --git a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
index b2158a6..de0f566 100644
--- a/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
+++ b/media/codec2/hal/aidl/include/codec2/aidl/ComponentStore.h
@@ -120,6 +120,9 @@
     std::shared_ptr<C2ComponentStore> mStore;
     std::vector<std::shared_ptr<C2ParamReflector>> mParamReflectors;
 
+    // Reflector helper for MultiAccessUnitHelper
+    std::shared_ptr<C2ReflectorHelper> mMultiAccessUnitReflector;
+
     std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
     std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
     std::set<C2String> mLoadedInterfaces;
diff --git a/media/codec2/hal/client/GraphicsTracker.cpp b/media/codec2/hal/client/GraphicsTracker.cpp
index 8d9e76e..bdfc409 100644
--- a/media/codec2/hal/client/GraphicsTracker.cpp
+++ b/media/codec2/hal/client/GraphicsTracker.cpp
@@ -34,7 +34,7 @@
 
 c2_status_t retrieveAHardwareBufferId(const C2ConstGraphicBlock &blk, uint64_t *bid) {
     std::shared_ptr<const _C2BlockPoolData> bpData = _C2BlockFactory::GetGraphicBlockPoolData(blk);
-    if (bpData->getType() != _C2BlockPoolData::TYPE_AHWBUFFER) {
+    if (!bpData || bpData->getType() != _C2BlockPoolData::TYPE_AHWBUFFER) {
         return C2_BAD_VALUE;
     }
     if (__builtin_available(android __ANDROID_API_T__, *)) {
@@ -824,6 +824,10 @@
     std::shared_ptr<BufferCache> cache;
     int slotId;
     sp<Fence> rFence;
+    if (mStopped.load() == true) {
+        ALOGE("cannot deallocate due to being stopped");
+        return C2_BAD_STATE;
+    }
     c2_status_t res = requestDeallocate(bid, fence, &completed, &updateDequeue,
                                         &cache, &slotId, &rFence);
     if (res != C2_OK) {
@@ -900,7 +904,10 @@
         cache->unblockSlot(buffer->mSlot);
         if (oldBuffer) {
             // migrated, register the new buffer to the cache.
-            cache->mBuffers.emplace(buffer->mSlot, buffer);
+            auto ret = cache->mBuffers.emplace(buffer->mSlot, buffer);
+            if (!ret.second) {
+                ret.first->second = buffer;
+            }
         }
     }
     mDeallocating.erase(origBid);
diff --git a/media/codec2/hal/client/client.cpp b/media/codec2/hal/client/client.cpp
index a137dbb..80735cb 100644
--- a/media/codec2/hal/client/client.cpp
+++ b/media/codec2/hal/client/client.cpp
@@ -2391,7 +2391,12 @@
                        "GraphicBufferAllocator was not created.";
             return C2_CORRUPTED;
         }
+        // Note: Consumer usage is set ahead of the HAL allocator(gba) being set.
+        // This is same as HIDL.
+        uint64_t consumerUsage = configConsumerUsage(surface);
         bool ret = gba->configure(surface, generation, maxDequeueCount);
+        ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx",
+              generation, (long long)consumerUsage);
         return ret ? C2_OK : C2_CORRUPTED;
     }
     uint64_t bqId = 0;
@@ -2419,41 +2424,9 @@
                                       mHidlBase1_2 ? &syncObj : nullptr);
     }
 
-    // set consumer bits
-    // TODO: should this get incorporated into setOutputSurface method so that consumer bits
-    // can be set atomically?
-    uint64_t consumerUsage = kDefaultConsumerUsage;
-    {
-        if (surface) {
-            uint64_t usage = 0;
-            status_t err = surface->getConsumerUsage(&usage);
-            if (err != NO_ERROR) {
-                ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
-                        err, asString(err));
-            } else {
-                // Note: we are adding the default usage because components must support
-                // producing output frames that can be displayed an all output surfaces.
-
-                // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
-                // is meaningful in a tunneled scenario; on one hand output buffers exist, but
-                // they do not exist inside of C2 scope. Any buffer usage shall be communicated
-                // through the sideband channel.
-
-                consumerUsage = usage | kDefaultConsumerUsage;
-            }
-        }
-
-        C2StreamUsageTuning::output outputUsage{
-                0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
-        std::vector<std::unique_ptr<C2SettingResult>> failures;
-        c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
-        if (err != C2_OK) {
-            ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
-                    err, asString(err));
-        }
-    }
+    uint64_t consumerUsage = configConsumerUsage(surface);
     ALOGD("setOutputSurface -- generation=%u consumer usage=%#llx%s",
-            generation, (long long)consumerUsage, syncObj ? " sync" : "");
+          generation, (long long)consumerUsage, syncObj ? " sync" : "");
 
     Return<c2_hidl::Status> transStatus = syncObj ?
             mHidlBase1_2->setOutputSurfaceWithSyncObj(
@@ -2495,6 +2468,44 @@
     return mOutputBufferQueue->outputBuffer(block, input, output);
 }
 
+uint64_t Codec2Client::Component::configConsumerUsage(
+        const sp<IGraphicBufferProducer>& surface) {
+    // set consumer bits
+    // TODO: should this get incorporated into setOutputSurface method so that consumer bits
+    // can be set atomically?
+    uint64_t consumerUsage = kDefaultConsumerUsage;
+    {
+        if (surface) {
+            uint64_t usage = 0;
+            status_t err = surface->getConsumerUsage(&usage);
+            if (err != NO_ERROR) {
+                ALOGD("setOutputSurface -- failed to get consumer usage bits (%d/%s). ignoring",
+                        err, asString(err));
+            } else {
+                // Note: we are adding the default usage because components must support
+                // producing output frames that can be displayed an all output surfaces.
+
+                // TODO: do not set usage for tunneled scenario. It is unclear if consumer usage
+                // is meaningful in a tunneled scenario; on one hand output buffers exist, but
+                // they do not exist inside of C2 scope. Any buffer usage shall be communicated
+                // through the sideband channel.
+
+                consumerUsage = usage | kDefaultConsumerUsage;
+            }
+        }
+
+        C2StreamUsageTuning::output outputUsage{
+                0u, C2AndroidMemoryUsage::FromGrallocUsage(consumerUsage).expected};
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        c2_status_t err = config({&outputUsage}, C2_MAY_BLOCK, &failures);
+        if (err != C2_OK) {
+            ALOGD("setOutputSurface -- failed to set consumer usage (%d/%s)",
+                    err, asString(err));
+        }
+    }
+    return consumerUsage;
+}
+
 void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
     if (mAidlBase) {
         // TODO b/311348680
diff --git a/media/codec2/hal/client/include/codec2/hidl/client.h b/media/codec2/hal/client/include/codec2/hidl/client.h
index 413e92e..7923f04 100644
--- a/media/codec2/hal/client/include/codec2/hidl/client.h
+++ b/media/codec2/hal/client/include/codec2/hidl/client.h
@@ -467,6 +467,9 @@
             const QueueBufferInput& input,
             QueueBufferOutput* output);
 
+    // configure consumer usage.
+    uint64_t configConsumerUsage(const sp<IGraphicBufferProducer>& surface);
+
     // Retrieve frame event history from the output surface.
     void pollForRenderedFrames(FrameEventHistoryDelta* delta);
 
diff --git a/media/codec2/hal/client/include/codec2/hidl/output.h b/media/codec2/hal/client/include/codec2/hidl/output.h
index ddb9855..108f0a6 100644
--- a/media/codec2/hal/client/include/codec2/hidl/output.h
+++ b/media/codec2/hal/client/include/codec2/hidl/output.h
@@ -96,6 +96,7 @@
     uint64_t mBqId;
     int32_t mMaxDequeueBufferCount;
     std::shared_ptr<int> mOwner;
+    std::shared_ptr<int> mConsumerAttachCount;
     // To migrate existing buffers
     sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; // find a better way
     std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
diff --git a/media/codec2/hal/client/output.cpp b/media/codec2/hal/client/output.cpp
index 54d78a0..2eb381b 100644
--- a/media/codec2/hal/client/output.cpp
+++ b/media/codec2/hal/client/output.cpp
@@ -261,6 +261,7 @@
         mGeneration = generation;
         mBqId = bqId;
         mOwner = std::make_shared<int>(0);
+        mConsumerAttachCount = std::make_shared<int>(0);
         mMaxDequeueBufferCount = maxDequeueBufferCount;
         if (igbp == nullptr) {
             return false;
@@ -522,6 +523,7 @@
     std::shared_ptr<C2SurfaceSyncMemory> syncMem;
     sp<IGraphicBufferProducer> outputIgbp;
     uint32_t outputGeneration = 0;
+    std::shared_ptr<int> consumerAttachCount;
     {
         std::unique_lock<std::mutex> l(mMutex);
         if (mStopped) {
@@ -529,6 +531,7 @@
         }
         outputIgbp = mIgbp;
         outputGeneration = mGeneration;
+        consumerAttachCount = mConsumerAttachCount;
         syncMem = mSyncMem;
     }
 
@@ -536,15 +539,42 @@
         auto syncVar = syncMem ? syncMem->mem() : nullptr;
         if (syncVar) {
             syncVar->lock();
-            syncVar->notifyQueuedLocked();
+            if (consumerAttachCount && *consumerAttachCount > 0) {
+                (*consumerAttachCount)--;
+            } else {
+                syncVar->notifyQueuedLocked();
+            }
             syncVar->unlock();
         }
     }
 }
 
 void OutputBufferQueue::onBufferAttached(uint32_t generation) {
-    // TODO
-    (void) generation;
+    std::shared_ptr<C2SurfaceSyncMemory> syncMem;
+    sp<IGraphicBufferProducer> outputIgbp;
+    uint32_t outputGeneration = 0;
+    std::shared_ptr<int> consumerAttachCount;
+    {
+        std::unique_lock<std::mutex> l(mMutex);
+        if (mStopped) {
+            return;
+        }
+        outputIgbp = mIgbp;
+        outputGeneration = mGeneration;
+        consumerAttachCount = mConsumerAttachCount;
+        syncMem = mSyncMem;
+    }
+
+    if (outputIgbp && generation == outputGeneration) {
+        auto syncVar = syncMem ? syncMem->mem() : nullptr;
+        if (syncVar) {
+            syncVar->lock();
+            if (consumerAttachCount) {
+                (*consumerAttachCount)++;
+            }
+            syncVar->unlock();
+        }
+    }
 }
 
 void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
diff --git a/media/codec2/hal/common/MultiAccessUnitHelper.cpp b/media/codec2/hal/common/MultiAccessUnitHelper.cpp
index 55bf7a9..b287b91 100644
--- a/media/codec2/hal/common/MultiAccessUnitHelper.cpp
+++ b/media/codec2/hal/common/MultiAccessUnitHelper.cpp
@@ -327,10 +327,10 @@
                 newWork->worklets.front()->component = inWork->worklets.front()->component;
                 std::vector<std::unique_ptr<C2Tuning>> tunings;
                 for (std::unique_ptr<C2Tuning>& tuning : inWork->worklets.front()->tunings) {
-                    tunings.push_back(std::move(
+                    tunings.push_back(
                             std::unique_ptr<C2Tuning>(
                                     static_cast<C2Tuning*>(
-                                            C2Param::Copy(*(tuning.get())).release()))));
+                                            C2Param::Copy(*(tuning.get())).release())));
                 }
                 newWork->worklets.front()->tunings = std::move(tunings);
             }
@@ -344,7 +344,7 @@
                     << inputOrdinal.frameIndex.peekull()
                     << ") -> newFrameIndex " << newFrameIdx
                     <<" : input ts " << inputOrdinal.timestamp.peekull();
-            sliceWork.push_back(std::move(cloneInputWork(w, w->input.flags)));
+            sliceWork.push_back(cloneInputWork(w, w->input.flags));
             if (!w->input.buffers.empty() && w->input.buffers.front() != nullptr) {
                 sliceWork.back()->input.buffers = std::move(w->input.buffers);
             }
@@ -853,4 +853,4 @@
     mLargeWork.reset();
 }
 
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
index 1ba1889..108ba06 100644
--- a/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.0/utils/ComponentStore.cpp
@@ -149,6 +149,14 @@
     }
 #endif
 
+    // MultiAccessUnit reflector helper is allocated once per store.
+    // All components in this store can reuse this reflector helper.
+    if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+        std::shared_ptr<C2ReflectorHelper> helper = std::make_shared<C2ReflectorHelper>();
+        mParamReflectors.push_back(helper);
+        mMultiAccessUnitReflector = helper;
+    }
+
     // Retrieve supported parameters from store
     using namespace std::placeholders;
     mInit = mConfigurable->init(mParameterCache);
@@ -207,12 +215,20 @@
     if (c2interface == nullptr) {
         return nullptr;
     }
+    // Framework support for Large audio frame feature depends on:
+    // 1. All feature flags enabled on platform
+    // 2. The capability of the implementation to use the same input buffer
+    //    for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+    // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
     if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
         c2_status_t err = C2_OK;
         C2ComponentDomainSetting domain;
         std::vector<std::unique_ptr<C2Param>> heapParams;
-        err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
-        if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+        C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+        err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+        if (err == C2_OK
+                && (domain.value == C2Component::DOMAIN_AUDIO)
+                && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
             std::vector<std::shared_ptr<C2ParamDescriptor>> params;
             bool isComponentSupportsLargeAudioFrame = false;
             c2interface->querySupportedParams_nb(&params);
@@ -225,7 +241,7 @@
             if (!isComponentSupportsLargeAudioFrame) {
                 multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
                         c2interface,
-                        std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+                        mMultiAccessUnitReflector);
             }
         }
     }
diff --git a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index 44b8ec1..847c90c 100644
--- a/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hal/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -124,6 +124,9 @@
     std::shared_ptr<C2ComponentStore> mStore;
     std::vector<std::shared_ptr<C2ParamReflector>> mParamReflectors;
 
+    // Reflector helper for MultiAccessUnitHelper
+    std::shared_ptr<C2ReflectorHelper> mMultiAccessUnitReflector;
+
     std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
     std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
     std::set<C2String> mLoadedInterfaces;
diff --git a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
index 1b86958..84f5d26 100644
--- a/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.1/utils/ComponentStore.cpp
@@ -149,6 +149,14 @@
     }
 #endif
 
+    // MultiAccessUnit reflector helper is allocated once per store.
+    // All components in this store can reuse this reflector helper.
+    if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+        std::shared_ptr<C2ReflectorHelper> helper = std::make_shared<C2ReflectorHelper>();
+        mParamReflectors.push_back(helper);
+        mMultiAccessUnitReflector = helper;
+    }
+
     // Retrieve supported parameters from store
     using namespace std::placeholders;
     mInit = mConfigurable->init(mParameterCache);
@@ -207,12 +215,20 @@
     if (c2interface == nullptr) {
         return nullptr;
     }
+    // Framework support for Large audio frame feature depends on:
+    // 1. All feature flags enabled on platform
+    // 2. The capability of the implementation to use the same input buffer
+    //    for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+    // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
     if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
         c2_status_t err = C2_OK;
         C2ComponentDomainSetting domain;
         std::vector<std::unique_ptr<C2Param>> heapParams;
-        err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
-        if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+        C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+        err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+        if (err == C2_OK
+                && (domain.value == C2Component::DOMAIN_AUDIO)
+                && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
             std::vector<std::shared_ptr<C2ParamDescriptor>> params;
             bool isComponentSupportsLargeAudioFrame = false;
             c2interface->querySupportedParams_nb(&params);
@@ -222,11 +238,10 @@
                     break;
                 }
             }
-
             if (!isComponentSupportsLargeAudioFrame) {
                 multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
                         c2interface,
-                        std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+                        mMultiAccessUnitReflector);
             }
         }
     }
diff --git a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
index 52d2945..9028149 100644
--- a/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
+++ b/media/codec2/hal/hidl/1.1/utils/include/codec2/hidl/1.1/ComponentStore.h
@@ -132,6 +132,9 @@
     std::shared_ptr<C2ComponentStore> mStore;
     std::vector<std::shared_ptr<C2ParamReflector>> mParamReflectors;
 
+    // Reflector helper for MultiAccessUnitHelper
+    std::shared_ptr<C2ReflectorHelper> mMultiAccessUnitReflector;
+
     std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
     std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
     std::set<C2String> mLoadedInterfaces;
diff --git a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
index 2e0386f..5585be8 100644
--- a/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
+++ b/media/codec2/hal/hidl/1.2/utils/ComponentStore.cpp
@@ -149,6 +149,14 @@
     }
 #endif
 
+    // MultiAccessUnit reflector helper is allocated once per store.
+    // All components in this store can reuse this reflector helper.
+    if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
+        std::shared_ptr<C2ReflectorHelper> helper = std::make_shared<C2ReflectorHelper>();
+        mParamReflectors.push_back(helper);
+        mMultiAccessUnitReflector = helper;
+    }
+
     // Retrieve supported parameters from store
     using namespace std::placeholders;
     mInit = mConfigurable->init(mParameterCache);
@@ -207,12 +215,20 @@
     if (c2interface == nullptr) {
         return nullptr;
     }
+    // Framework support for Large audio frame feature depends on:
+    // 1. All feature flags enabled on platform
+    // 2. The capability of the implementation to use the same input buffer
+    //    for different C2Work (C2Config::api_feature_t::API_SAME_INPUT_BUFFER)
+    // 3. Implementation does not inherently support C2LargeFrame::output::PARAM_TYPE param.
     if (MultiAccessUnitHelper::isEnabledOnPlatform()) {
         c2_status_t err = C2_OK;
         C2ComponentDomainSetting domain;
         std::vector<std::unique_ptr<C2Param>> heapParams;
-        err = c2interface->query_vb({&domain}, {}, C2_MAY_BLOCK, &heapParams);
-        if (err == C2_OK && (domain.value == C2Component::DOMAIN_AUDIO)) {
+        C2ApiFeaturesSetting features = (C2Config::api_feature_t)0;
+        err = c2interface->query_vb({&domain, &features}, {}, C2_MAY_BLOCK, &heapParams);
+        if (err == C2_OK
+                && (domain.value == C2Component::DOMAIN_AUDIO)
+                && ((features.value & C2Config::api_feature_t::API_SAME_INPUT_BUFFER) != 0)) {
             std::vector<std::shared_ptr<C2ParamDescriptor>> params;
             bool isComponentSupportsLargeAudioFrame = false;
             c2interface->querySupportedParams_nb(&params);
@@ -225,7 +241,7 @@
             if (!isComponentSupportsLargeAudioFrame) {
                 multiAccessUnitIntf = std::make_shared<MultiAccessUnitInterface>(
                         c2interface,
-                        std::static_pointer_cast<C2ReflectorHelper>(mParamReflectors[0]));
+                        mMultiAccessUnitReflector);
             }
         }
     }
diff --git a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h
index 1b209e2..4fd260b 100644
--- a/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h
+++ b/media/codec2/hal/hidl/1.2/utils/include/codec2/hidl/1.2/ComponentStore.h
@@ -139,6 +139,9 @@
     std::shared_ptr<C2ComponentStore> mStore;
     std::vector<std::shared_ptr<C2ParamReflector>> mParamReflectors;
 
+    // Reflector helper for MultiAccessUnitHelper
+    std::shared_ptr<C2ReflectorHelper> mMultiAccessUnitReflector;
+
     std::map<C2Param::CoreIndex, std::shared_ptr<C2StructDescriptor>> mStructDescriptors;
     std::set<C2Param::CoreIndex> mUnsupportedStructDescriptors;
     std::set<C2String> mLoadedInterfaces;
diff --git a/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp
index 47412b7..34872f0 100644
--- a/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp
+++ b/media/codec2/hal/plugin/samples/SampleFilterPlugin.cpp
@@ -856,21 +856,31 @@
     C2String getName() const override { return "android.sample.filter-plugin-store"; }
     c2_status_t createComponent(
             C2String name, std::shared_ptr<C2Component>* const component) override {
-        if (mFactories.count(name) == 0) {
+        auto it = std::find_if(
+                mFactories.begin(), mFactories.end(),
+                [&name](const std::unique_ptr<ComponentFactory> &factory) {
+                    return name == factory->getTraits()->name;
+                });
+        if (it == mFactories.end()) {
             return C2_BAD_VALUE;
         }
-        return mFactories.at(name)->createComponent(++mNodeId, component);
+        return (*it)->createComponent(++mNodeId, component);
     }
     c2_status_t createInterface(
             C2String name, std::shared_ptr<C2ComponentInterface>* const interface) override {
-        if (mFactories.count(name) == 0) {
+        auto it = std::find_if(
+                mFactories.begin(), mFactories.end(),
+                [&name](const std::unique_ptr<ComponentFactory> &factory) {
+                    return name == factory->getTraits()->name;
+                });
+        if (it == mFactories.end()) {
             return C2_BAD_VALUE;
         }
-        return mFactories.at(name)->createInterface(++mNodeId, interface);
+        return (*it)->createInterface(++mNodeId, interface);
     }
     std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override {
         std::vector<std::shared_ptr<const C2Component::Traits>> ret;
-        for (const auto &[name, factory] : mFactories) {
+        for (const auto &factory : mFactories) {
             ret.push_back(factory->getTraits());
         }
         return ret;
@@ -951,20 +961,18 @@
 
     template <class T>
     static void AddFactory(
-            std::map<C2String, std::unique_ptr<ComponentFactory>> *factories,
+            std::vector<std::unique_ptr<ComponentFactory>> *factories,
             const std::shared_ptr<C2ReflectorHelper> &reflector) {
         std::shared_ptr<C2ComponentInterface> intf{new typename T::Interface(0, reflector)};
         std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
         CHECK(C2InterfaceUtils::FillTraitsFromInterface(traits.get(), intf))
                 << "Failed to fill traits from interface";
-        factories->emplace(
-                traits->name,
-                new ComponentFactoryImpl<T>(traits, reflector));
+        factories->emplace_back(new ComponentFactoryImpl<T>(traits, reflector));
     }
 
-    static std::map<C2String, std::unique_ptr<ComponentFactory>> CreateFactories(
+    static std::vector<std::unique_ptr<ComponentFactory>> CreateFactories(
             const std::shared_ptr<C2ReflectorHelper> &reflector) {
-        std::map<C2String, std::unique_ptr<ComponentFactory>> factories;
+        std::vector<std::unique_ptr<ComponentFactory>> factories;
         AddFactory<SampleToneMappingFilter>(&factories, reflector);
         return factories;
     }
@@ -977,7 +985,7 @@
         }
     } mIntf;
 
-    const std::map<C2String, std::unique_ptr<ComponentFactory>> mFactories;
+    const std::vector<std::unique_ptr<ComponentFactory>> mFactories;
 
     std::atomic_int32_t mNodeId{0};
 };
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 64d8f07..632eaed 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -96,11 +96,14 @@
 
 public:
     static sp<CCodecWatchdog> getInstance() {
-        static sp<CCodecWatchdog> instance(new CCodecWatchdog);
-        static std::once_flag flag;
-        // Call Init() only once.
-        std::call_once(flag, Init, instance);
-        return instance;
+        static sp<CCodecWatchdog> sInstance = [] {
+            sp<CCodecWatchdog> instance = new CCodecWatchdog;
+            // the instance should never get destructed
+            instance->incStrong((void *)CCodecWatchdog::getInstance);
+            instance->init();
+            return instance;
+        }();
+        return sInstance;
     }
 
     ~CCodecWatchdog() = default;
@@ -146,11 +149,11 @@
 private:
     CCodecWatchdog() : mLooper(new ALooper) {}
 
-    static void Init(const sp<CCodecWatchdog> &thiz) {
-        ALOGV("Init");
-        thiz->mLooper->setName("CCodecWatchdog");
-        thiz->mLooper->registerHandler(thiz);
-        thiz->mLooper->start();
+    void init() {
+        ALOGV("init");
+        mLooper->setName("CCodecWatchdog");
+        mLooper->registerHandler(this);
+        mLooper->start();
     }
 
     sp<ALooper> mLooper;
@@ -509,9 +512,14 @@
         uint64_t usage = mConfig.mUsage;
         (void)(*node)->setConsumerUsage((int64_t)usage);
 
+        // AIDL does not define legacy dataspace.
+        android_dataspace_t dataspace = mDataSpace;
+        if (android::media::codec::provider_->dataspace_v0_partial()) {
+            ColorUtils::convertDataSpaceToV0(dataspace);
+        }
         return fromAidlStatus(mSource->configure(
                 (*node), static_cast<::aidl::android::hardware::graphics::common::Dataspace>(
-                        mDataSpace)));
+                        dataspace)));
     }
 
     void disconnect() override {
@@ -2673,7 +2681,7 @@
                         mChannel->setInfoBuffer(std::make_shared<C2InfoBuffer>(info));
                     }
                 } else {
-                    ALOGE("Ignoring param key %s as buffer size %d is less than expected "
+                    ALOGE("Ignoring param key %s as buffer size %zu is less than expected "
                           "buffer size %d",
                           PARAMETER_KEY_QP_OFFSET_MAP, mapSize, expectedMapSize);
                 }
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index b5f885b..3ef2f84 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -2646,8 +2646,8 @@
                                 bufferMetadata->m.values[nMeta];
                         flag = convertFlags(bufferMetadataStruct.flags, false);
                         accessUnitInfos.emplace_back(flag,
-                                static_cast<size_t>(bufferMetadataStruct.size),
-                                static_cast<size_t>(bufferMetadataStruct.timestamp));
+                                bufferMetadataStruct.size,
+                                bufferMetadataStruct.timestamp);
                     }
                     sp<WrapperObject<std::vector<AccessUnitInfo>>> obj{
                         new WrapperObject<std::vector<AccessUnitInfo>>{accessUnitInfos}};
@@ -2840,7 +2840,6 @@
         work->input.infoBuffers.emplace_back(*buffer);
         work->worklets.emplace_back(new C2Worklet);
         items.push_back(std::move(work));
-        c2_status_t err = mComponent->queue(&items);
     }
 }
 
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 36725ec..a943626 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -1896,7 +1896,8 @@
                 std::vector<C2QpOffsetRectStruct> c2QpOffsetRects;
                 char mutableStrQpOffsetRects[strlen(qpOffsetRects.c_str()) + 1];
                 strcpy(mutableStrQpOffsetRects, qpOffsetRects.c_str());
-                char* box = strtok(mutableStrQpOffsetRects, ";");
+                char* savePtr;
+                char* box = strtok_r(mutableStrQpOffsetRects, ";", &savePtr);
                 while (box != nullptr) {
                     int top, left, bottom, right, offset;
                     if (sscanf(box, "%d,%d-%d,%d=%d", &top, &left, &bottom, &right, &offset) == 5) {
@@ -1914,7 +1915,7 @@
                     } else {
                         ALOGE("Rects configuration %s doesn't follow the string pattern.", box);
                     }
-                    box = strtok(nullptr, ";");
+                    box = strtok_r(nullptr, ";", &savePtr);
                 }
                 if (c2QpOffsetRects.size() != 0) {
                     const std::unique_ptr<C2StreamQpOffsetRects::output> regions =
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 2550dcf..7d4e8ab 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -20,6 +20,8 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
+#include <android_media_codec.h>
+
 #include <aidl/android/hardware/graphics/common/Cta861_3.h>
 #include <aidl/android/hardware/graphics/common/Smpte2086.h>
 #include <android-base/no_destructor.h>
@@ -33,6 +35,7 @@
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/ColorUtils.h>
 #include <mediadrm/ICrypto.h>
 #include <nativebase/nativebase.h>
 #include <ui/GraphicBufferMapper.h>
@@ -43,6 +46,7 @@
 #include <C2Debug.h>
 
 #include "Codec2Buffer.h"
+#include "Codec2BufferUtils.h"
 
 namespace android {
 
@@ -215,482 +219,6 @@
     mBufferRef.reset();
 }
 
-// GraphicView2MediaImageConverter
-
-namespace {
-
-class GraphicView2MediaImageConverter {
-public:
-    /**
-     * Creates a C2GraphicView <=> MediaImage converter
-     *
-     * \param view C2GraphicView object
-     * \param format buffer format
-     * \param copy whether the converter is used for copy or not
-     */
-    GraphicView2MediaImageConverter(
-            const C2GraphicView &view, const sp<AMessage> &format, bool copy)
-        : mInitCheck(NO_INIT),
-          mView(view),
-          mWidth(view.width()),
-          mHeight(view.height()),
-          mAllocatedDepth(0),
-          mBackBufferSize(0),
-          mMediaImage(new ABuffer(sizeof(MediaImage2))) {
-        ATRACE_CALL();
-        if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
-            mClientColorFormat = COLOR_FormatYUV420Flexible;
-        }
-        if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
-            mComponentColorFormat = COLOR_FormatYUV420Flexible;
-        }
-        if (view.error() != C2_OK) {
-            ALOGD("Converter: view.error() = %d", view.error());
-            mInitCheck = BAD_VALUE;
-            return;
-        }
-        MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
-        const C2PlanarLayout &layout = view.layout();
-        if (layout.numPlanes == 0) {
-            ALOGD("Converter: 0 planes");
-            mInitCheck = BAD_VALUE;
-            return;
-        }
-        memset(mediaImage, 0, sizeof(*mediaImage));
-        mAllocatedDepth = layout.planes[0].allocatedDepth;
-        uint32_t bitDepth = layout.planes[0].bitDepth;
-
-        // align width and height to support subsampling cleanly
-        uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
-        uint32_t vStride = align(view.crop().height, 2);
-
-        bool tryWrapping = !copy;
-
-        switch (layout.type) {
-            case C2PlanarLayout::TYPE_YUV: {
-                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
-                if (layout.numPlanes != 3) {
-                    ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
-                    mInitCheck = BAD_VALUE;
-                    return;
-                }
-                std::optional<int> clientBitDepth = {};
-                switch (mClientColorFormat) {
-                    case COLOR_FormatYUVP010:
-                        clientBitDepth = 10;
-                        break;
-                    case COLOR_FormatYUV411PackedPlanar:
-                    case COLOR_FormatYUV411Planar:
-                    case COLOR_FormatYUV420Flexible:
-                    case COLOR_FormatYUV420PackedPlanar:
-                    case COLOR_FormatYUV420PackedSemiPlanar:
-                    case COLOR_FormatYUV420Planar:
-                    case COLOR_FormatYUV420SemiPlanar:
-                    case COLOR_FormatYUV422Flexible:
-                    case COLOR_FormatYUV422PackedPlanar:
-                    case COLOR_FormatYUV422PackedSemiPlanar:
-                    case COLOR_FormatYUV422Planar:
-                    case COLOR_FormatYUV422SemiPlanar:
-                    case COLOR_FormatYUV444Flexible:
-                    case COLOR_FormatYUV444Interleaved:
-                        clientBitDepth = 8;
-                        break;
-                    default:
-                        // no-op; used with optional
-                        break;
-
-                }
-                // conversion fails if client bit-depth and the component bit-depth differs
-                if ((clientBitDepth) && (bitDepth != clientBitDepth.value())) {
-                    ALOGD("Bit depth of client: %d and component: %d differs",
-                        *clientBitDepth, bitDepth);
-                    mInitCheck = BAD_VALUE;
-                    return;
-                }
-                C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
-                C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
-                C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
-                if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
-                        || uPlane.channel != C2PlaneInfo::CHANNEL_CB
-                        || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
-                    ALOGD("Converter: not YUV layout");
-                    mInitCheck = BAD_VALUE;
-                    return;
-                }
-                bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
-                        && uPlane.rowSampling == 2 && uPlane.colSampling == 2
-                        && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
-                if (yuv420888) {
-                    for (uint32_t i = 0; i < 3; ++i) {
-                        const C2PlaneInfo &plane = layout.planes[i];
-                        if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
-                            yuv420888 = false;
-                            break;
-                        }
-                    }
-                    yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
-                }
-                int32_t copyFormat = mClientColorFormat;
-                if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
-                    if (uPlane.colInc == 2 && vPlane.colInc == 2
-                            && yPlane.rowInc == uPlane.rowInc) {
-                        copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
-                    } else if (uPlane.colInc == 1 && vPlane.colInc == 1
-                            && yPlane.rowInc == uPlane.rowInc * 2) {
-                        copyFormat = COLOR_FormatYUV420PackedPlanar;
-                    }
-                }
-                ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
-                        "v:{colInc=%d rowInc=%d}",
-                        mClientColorFormat,
-                        yPlane.colInc, yPlane.rowInc,
-                        uPlane.colInc, uPlane.rowInc,
-                        vPlane.colInc, vPlane.rowInc);
-                switch (copyFormat) {
-                    case COLOR_FormatYUV420Flexible:
-                    case COLOR_FormatYUV420Planar:
-                    case COLOR_FormatYUV420PackedPlanar:
-                        mediaImage->mPlane[mediaImage->Y].mOffset = 0;
-                        mediaImage->mPlane[mediaImage->Y].mColInc = 1;
-                        mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
-                        mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
-
-                        mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
-                        mediaImage->mPlane[mediaImage->U].mColInc = 1;
-                        mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
-                        mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
-                        mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
-
-                        mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
-                        mediaImage->mPlane[mediaImage->V].mColInc = 1;
-                        mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
-                        mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
-                        mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
-
-                        if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
-                            tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
-                                    && yPlane.rowInc == uPlane.rowInc * 2
-                                    && view.data()[0] < view.data()[1]
-                                    && view.data()[1] < view.data()[2];
-                        }
-                        break;
-
-                    case COLOR_FormatYUV420SemiPlanar:
-                    case COLOR_FormatYUV420PackedSemiPlanar:
-                        mediaImage->mPlane[mediaImage->Y].mOffset = 0;
-                        mediaImage->mPlane[mediaImage->Y].mColInc = 1;
-                        mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
-                        mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
-
-                        mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
-                        mediaImage->mPlane[mediaImage->U].mColInc = 2;
-                        mediaImage->mPlane[mediaImage->U].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
-                        mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
-
-                        mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
-                        mediaImage->mPlane[mediaImage->V].mColInc = 2;
-                        mediaImage->mPlane[mediaImage->V].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
-                        mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
-
-                        if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
-                            tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
-                                    && yPlane.rowInc == uPlane.rowInc
-                                    && view.data()[0] < view.data()[1]
-                                    && view.data()[1] < view.data()[2];
-                        }
-                        break;
-
-                    case COLOR_FormatYUVP010:
-                        // stride is in bytes
-                        mediaImage->mPlane[mediaImage->Y].mOffset = 0;
-                        mediaImage->mPlane[mediaImage->Y].mColInc = 2;
-                        mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
-                        mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
-
-                        mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
-                        mediaImage->mPlane[mediaImage->U].mColInc = 4;
-                        mediaImage->mPlane[mediaImage->U].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
-                        mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
-
-                        mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
-                        mediaImage->mPlane[mediaImage->V].mColInc = 4;
-                        mediaImage->mPlane[mediaImage->V].mRowInc = stride;
-                        mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
-                        mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
-                        if (tryWrapping) {
-                            tryWrapping = yPlane.allocatedDepth == 16
-                                    && uPlane.allocatedDepth == 16
-                                    && vPlane.allocatedDepth == 16
-                                    && yPlane.bitDepth == 10
-                                    && uPlane.bitDepth == 10
-                                    && vPlane.bitDepth == 10
-                                    && yPlane.rightShift == 6
-                                    && uPlane.rightShift == 6
-                                    && vPlane.rightShift == 6
-                                    && yPlane.rowSampling == 1 && yPlane.colSampling == 1
-                                    && uPlane.rowSampling == 2 && uPlane.colSampling == 2
-                                    && vPlane.rowSampling == 2 && vPlane.colSampling == 2
-                                    && yPlane.colInc == 2
-                                    && uPlane.colInc == 4
-                                    && vPlane.colInc == 4
-                                    && yPlane.rowInc == uPlane.rowInc
-                                    && yPlane.rowInc == vPlane.rowInc;
-                        }
-                        break;
-
-                    default: {
-                        // default to fully planar format --- this will be overridden if wrapping
-                        // TODO: keep interleaved format
-                        int32_t colInc = divUp(mAllocatedDepth, 8u);
-                        int32_t rowInc = stride * colInc / yPlane.colSampling;
-                        mediaImage->mPlane[mediaImage->Y].mOffset = 0;
-                        mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
-                        mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
-                        mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
-                        mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
-                        int32_t offset = rowInc * vStride / yPlane.rowSampling;
-
-                        rowInc = stride * colInc / uPlane.colSampling;
-                        mediaImage->mPlane[mediaImage->U].mOffset = offset;
-                        mediaImage->mPlane[mediaImage->U].mColInc = colInc;
-                        mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
-                        mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
-                        mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
-                        offset += rowInc * vStride / uPlane.rowSampling;
-
-                        rowInc = stride * colInc / vPlane.colSampling;
-                        mediaImage->mPlane[mediaImage->V].mOffset = offset;
-                        mediaImage->mPlane[mediaImage->V].mColInc = colInc;
-                        mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
-                        mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
-                        mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
-                        break;
-                    }
-                }
-                break;
-            }
-
-            case C2PlanarLayout::TYPE_YUVA:
-                ALOGD("Converter: unrecognized color format "
-                        "(client %d component %d) for YUVA layout",
-                        mClientColorFormat, mComponentColorFormat);
-                mInitCheck = NO_INIT;
-                return;
-            case C2PlanarLayout::TYPE_RGB:
-                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
-                // TODO: support MediaImage layout
-                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:
-                mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
-                // TODO: support MediaImage layout
-                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) {
-                    const C2PlaneInfo &plane = layout.planes[0];
-                    if (plane.colInc < 0 || plane.rowInc < 0) {
-                        // Copy-only if we have negative colInc/rowInc
-                        tryWrapping = false;
-                    }
-                    mediaImage->mPlane[0].mOffset = 0;
-                    mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
-                    mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
-                    mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
-                    mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
-                } else {
-                    ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
-                            mClientColorFormat, mComponentColorFormat);
-                    mInitCheck = NO_INIT;
-                    return;
-                }
-                break;
-        }
-        if (tryWrapping) {
-            // try to map directly. check if the planes are near one another
-            const uint8_t *minPtr = mView.data()[0];
-            const uint8_t *maxPtr = mView.data()[0];
-            int32_t planeSize = 0;
-            for (uint32_t i = 0; i < layout.numPlanes; ++i) {
-                const C2PlaneInfo &plane = layout.planes[i];
-                int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
-                ssize_t minOffset = plane.minOffset(
-                        mWidth / plane.colSampling, mHeight / plane.rowSampling);
-                ssize_t maxOffset = plane.maxOffset(
-                        mWidth / plane.colSampling, mHeight / plane.rowSampling);
-                if (minPtr > mView.data()[i] + minOffset) {
-                    minPtr = mView.data()[i] + minOffset;
-                }
-                if (maxPtr < mView.data()[i] + maxOffset) {
-                    maxPtr = mView.data()[i] + maxOffset;
-                }
-                planeSize += planeStride * divUp(mAllocatedDepth, 8u)
-                        * align(mHeight, 64) / plane.rowSampling;
-            }
-
-            if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) {
-                // FIXME: this is risky as reading/writing data out of bound results
-                //        in an undefined behavior, but gralloc does assume a
-                //        contiguous mapping
-                for (uint32_t i = 0; i < layout.numPlanes; ++i) {
-                    const C2PlaneInfo &plane = layout.planes[i];
-                    mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
-                    mediaImage->mPlane[i].mColInc = plane.colInc;
-                    mediaImage->mPlane[i].mRowInc = plane.rowInc;
-                    mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
-                    mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
-                }
-                mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr);
-                ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
-            }
-        }
-        mediaImage->mNumPlanes = layout.numPlanes;
-        mediaImage->mWidth = view.crop().width;
-        mediaImage->mHeight = view.crop().height;
-        mediaImage->mBitDepth = bitDepth;
-        mediaImage->mBitDepthAllocated = mAllocatedDepth;
-
-        uint32_t bufferSize = 0;
-        for (uint32_t i = 0; i < layout.numPlanes; ++i) {
-            const C2PlaneInfo &plane = layout.planes[i];
-            if (plane.allocatedDepth < plane.bitDepth
-                    || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
-                ALOGD("rightShift value of %u unsupported", plane.rightShift);
-                mInitCheck = BAD_VALUE;
-                return;
-            }
-            if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
-                ALOGD("endianness value of %u unsupported", plane.endianness);
-                mInitCheck = BAD_VALUE;
-                return;
-            }
-            if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
-                ALOGD("different allocatedDepth/bitDepth per plane unsupported");
-                mInitCheck = BAD_VALUE;
-                return;
-            }
-            // stride is in bytes
-            bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
-        }
-
-        mBackBufferSize = bufferSize;
-        mInitCheck = OK;
-    }
-
-    status_t initCheck() const { return mInitCheck; }
-
-    uint32_t backBufferSize() const { return mBackBufferSize; }
-
-    /**
-     * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
-     * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
-     * data into a backing buffer explicitly.
-     *
-     * \return media buffer. This is null if wrapping failed.
-     */
-    sp<ABuffer> wrap() const {
-        if (mBackBuffer == nullptr) {
-            return mWrapped;
-        }
-        return nullptr;
-    }
-
-    bool setBackBuffer(const sp<ABuffer> &backBuffer) {
-        if (backBuffer == nullptr) {
-            return false;
-        }
-        if (backBuffer->capacity() < mBackBufferSize) {
-            return false;
-        }
-        backBuffer->setRange(0, mBackBufferSize);
-        mBackBuffer = backBuffer;
-        return true;
-    }
-
-    /**
-     * Copy C2GraphicView to MediaImage2.
-     */
-    status_t copyToMediaImage() {
-        ATRACE_CALL();
-        if (mInitCheck != OK) {
-            return mInitCheck;
-        }
-        return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
-    }
-
-    const sp<ABuffer> &imageData() const { return mMediaImage; }
-
-private:
-    status_t mInitCheck;
-
-    const C2GraphicView mView;
-    uint32_t mWidth;
-    uint32_t mHeight;
-    int32_t mClientColorFormat;  ///< SDK color format for MediaImage
-    int32_t mComponentColorFormat;  ///< SDK color format from component
-    sp<ABuffer> mWrapped;  ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
-    uint32_t mAllocatedDepth;
-    uint32_t mBackBufferSize;
-    sp<ABuffer> mMediaImage;
-    std::function<sp<ABuffer>(size_t)> mAlloc;
-
-    sp<ABuffer> mBackBuffer;    ///< backing buffer if we have to copy C2Buffer <=> ABuffer
-
-    MediaImage2 *getMediaImage() {
-        return (MediaImage2 *)mMediaImage->base();
-    }
-};
-
-}  // namespace
-
 // GraphicBlockBuffer
 
 // static
@@ -1210,6 +738,10 @@
         // Gralloc4 not supported; nothing to do
         return err;
     }
+    // Use V0 dataspaces for Gralloc4+
+    if (android::media::codec::provider_->dataspace_v0_partial()) {
+        ColorUtils::convertDataSpaceToV0(dataSpace);
+    }
     status_t status = mapper.setDataspace(buffer.get(), static_cast<ui::Dataspace>(dataSpace));
     if (status != OK) {
        err = C2_CORRUPTED;
diff --git a/media/codec2/sfplugin/Codec2Buffer.h b/media/codec2/sfplugin/Codec2Buffer.h
index 5e96921..8c5e909 100644
--- a/media/codec2/sfplugin/Codec2Buffer.h
+++ b/media/codec2/sfplugin/Codec2Buffer.h
@@ -44,28 +44,6 @@
 }  // namespace drm
 }  // namespace hardware
 
-/**
- * Copies a graphic view into a media image.
- *
- * \param imgBase base of MediaImage
- * \param img MediaImage data
- * \param view graphic view
- *
- * \return OK on success
- */
-status_t ImageCopy(uint8_t *imgBase, const MediaImage2 *img, const C2GraphicView &view);
-
-/**
- * Copies a media image into a graphic view.
- *
- * \param view graphic view
- * \param imgBase base of MediaImage
- * \param img MediaImage data
- *
- * \return OK on success
- */
-status_t ImageCopy(C2GraphicView &view, const uint8_t *imgBase, const MediaImage2 *img);
-
 class Codec2Buffer : public MediaCodecBuffer {
 public:
     using MediaCodecBuffer::MediaCodecBuffer;
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
index 75e9bbc..574f1b9 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.cpp
@@ -27,7 +27,10 @@
 
 #include <android/hardware_buffer.h>
 #include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/MediaCodecConstants.h>
 
 #include <C2Debug.h>
 
@@ -787,4 +790,438 @@
     return MemoryBlockPool().fetch(size);
 }
 
+GraphicView2MediaImageConverter::GraphicView2MediaImageConverter(
+        const C2GraphicView &view, const sp<AMessage> &format, bool copy)
+    : mInitCheck(NO_INIT),
+        mView(view),
+        mWidth(view.width()),
+        mHeight(view.height()),
+        mAllocatedDepth(0),
+        mBackBufferSize(0),
+        mMediaImage(new ABuffer(sizeof(MediaImage2))) {
+    ATRACE_CALL();
+    if (!format->findInt32(KEY_COLOR_FORMAT, &mClientColorFormat)) {
+        mClientColorFormat = COLOR_FormatYUV420Flexible;
+    }
+    if (!format->findInt32("android._color-format", &mComponentColorFormat)) {
+        mComponentColorFormat = COLOR_FormatYUV420Flexible;
+    }
+    if (view.error() != C2_OK) {
+        ALOGD("Converter: view.error() = %d", view.error());
+        mInitCheck = BAD_VALUE;
+        return;
+    }
+    MediaImage2 *mediaImage = (MediaImage2 *)mMediaImage->base();
+    const C2PlanarLayout &layout = view.layout();
+    if (layout.numPlanes == 0) {
+        ALOGD("Converter: 0 planes");
+        mInitCheck = BAD_VALUE;
+        return;
+    }
+    memset(mediaImage, 0, sizeof(*mediaImage));
+    mAllocatedDepth = layout.planes[0].allocatedDepth;
+    uint32_t bitDepth = layout.planes[0].bitDepth;
+
+    // align width and height to support subsampling cleanly
+    uint32_t stride = align(view.crop().width, 2) * divUp(layout.planes[0].allocatedDepth, 8u);
+    uint32_t vStride = align(view.crop().height, 2);
+
+    bool tryWrapping = !copy;
+
+    switch (layout.type) {
+        case C2PlanarLayout::TYPE_YUV: {
+            mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
+            if (layout.numPlanes != 3) {
+                ALOGD("Converter: %d planes for YUV layout", layout.numPlanes);
+                mInitCheck = BAD_VALUE;
+                return;
+            }
+            std::optional<int> clientBitDepth = {};
+            switch (mClientColorFormat) {
+                case COLOR_FormatYUVP010:
+                    clientBitDepth = 10;
+                    break;
+                case COLOR_FormatYUV411PackedPlanar:
+                case COLOR_FormatYUV411Planar:
+                case COLOR_FormatYUV420Flexible:
+                case COLOR_FormatYUV420PackedPlanar:
+                case COLOR_FormatYUV420PackedSemiPlanar:
+                case COLOR_FormatYUV420Planar:
+                case COLOR_FormatYUV420SemiPlanar:
+                case COLOR_FormatYUV422Flexible:
+                case COLOR_FormatYUV422PackedPlanar:
+                case COLOR_FormatYUV422PackedSemiPlanar:
+                case COLOR_FormatYUV422Planar:
+                case COLOR_FormatYUV422SemiPlanar:
+                case COLOR_FormatYUV444Flexible:
+                case COLOR_FormatYUV444Interleaved:
+                    clientBitDepth = 8;
+                    break;
+                default:
+                    // no-op; used with optional
+                    break;
+
+            }
+            // conversion fails if client bit-depth and the component bit-depth differs
+            if ((clientBitDepth) && (bitDepth != clientBitDepth.value())) {
+                ALOGD("Bit depth of client: %d and component: %d differs",
+                    *clientBitDepth, bitDepth);
+                mInitCheck = BAD_VALUE;
+                return;
+            }
+            C2PlaneInfo yPlane = layout.planes[C2PlanarLayout::PLANE_Y];
+            C2PlaneInfo uPlane = layout.planes[C2PlanarLayout::PLANE_U];
+            C2PlaneInfo vPlane = layout.planes[C2PlanarLayout::PLANE_V];
+            if (yPlane.channel != C2PlaneInfo::CHANNEL_Y
+                    || uPlane.channel != C2PlaneInfo::CHANNEL_CB
+                    || vPlane.channel != C2PlaneInfo::CHANNEL_CR) {
+                ALOGD("Converter: not YUV layout");
+                mInitCheck = BAD_VALUE;
+                return;
+            }
+            bool yuv420888 = yPlane.rowSampling == 1 && yPlane.colSampling == 1
+                    && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+                    && vPlane.rowSampling == 2 && vPlane.colSampling == 2;
+            if (yuv420888) {
+                for (uint32_t i = 0; i < 3; ++i) {
+                    const C2PlaneInfo &plane = layout.planes[i];
+                    if (plane.allocatedDepth != 8 || plane.bitDepth != 8) {
+                        yuv420888 = false;
+                        break;
+                    }
+                }
+                yuv420888 = yuv420888 && yPlane.colInc == 1 && uPlane.rowInc == vPlane.rowInc;
+            }
+            int32_t copyFormat = mClientColorFormat;
+            if (yuv420888 && mClientColorFormat == COLOR_FormatYUV420Flexible) {
+                if (uPlane.colInc == 2 && vPlane.colInc == 2
+                        && yPlane.rowInc == uPlane.rowInc) {
+                    copyFormat = COLOR_FormatYUV420PackedSemiPlanar;
+                } else if (uPlane.colInc == 1 && vPlane.colInc == 1
+                        && yPlane.rowInc == uPlane.rowInc * 2) {
+                    copyFormat = COLOR_FormatYUV420PackedPlanar;
+                }
+            }
+            ALOGV("client_fmt=0x%x y:{colInc=%d rowInc=%d} u:{colInc=%d rowInc=%d} "
+                    "v:{colInc=%d rowInc=%d}",
+                    mClientColorFormat,
+                    yPlane.colInc, yPlane.rowInc,
+                    uPlane.colInc, uPlane.rowInc,
+                    vPlane.colInc, vPlane.rowInc);
+            switch (copyFormat) {
+                case COLOR_FormatYUV420Flexible:
+                case COLOR_FormatYUV420Planar:
+                case COLOR_FormatYUV420PackedPlanar:
+                    mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+                    mediaImage->mPlane[mediaImage->Y].mColInc = 1;
+                    mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
+                    mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
+
+                    mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
+                    mediaImage->mPlane[mediaImage->U].mColInc = 1;
+                    mediaImage->mPlane[mediaImage->U].mRowInc = stride / 2;
+                    mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
+                    mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
+
+                    mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride * 5 / 4;
+                    mediaImage->mPlane[mediaImage->V].mColInc = 1;
+                    mediaImage->mPlane[mediaImage->V].mRowInc = stride / 2;
+                    mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
+                    mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+                    if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+                        tryWrapping = yuv420888 && uPlane.colInc == 1 && vPlane.colInc == 1
+                                && yPlane.rowInc == uPlane.rowInc * 2
+                                && view.data()[0] < view.data()[1]
+                                && view.data()[1] < view.data()[2];
+                    }
+                    break;
+
+                case COLOR_FormatYUV420SemiPlanar:
+                case COLOR_FormatYUV420PackedSemiPlanar:
+                    mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+                    mediaImage->mPlane[mediaImage->Y].mColInc = 1;
+                    mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
+                    mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
+
+                    mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
+                    mediaImage->mPlane[mediaImage->U].mColInc = 2;
+                    mediaImage->mPlane[mediaImage->U].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
+                    mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
+
+                    mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 1;
+                    mediaImage->mPlane[mediaImage->V].mColInc = 2;
+                    mediaImage->mPlane[mediaImage->V].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
+                    mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+
+                    if (tryWrapping && mClientColorFormat != COLOR_FormatYUV420Flexible) {
+                        tryWrapping = yuv420888 && uPlane.colInc == 2 && vPlane.colInc == 2
+                                && yPlane.rowInc == uPlane.rowInc
+                                && view.data()[0] < view.data()[1]
+                                && view.data()[1] < view.data()[2];
+                    }
+                    break;
+
+                case COLOR_FormatYUVP010:
+                    // stride is in bytes
+                    mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+                    mediaImage->mPlane[mediaImage->Y].mColInc = 2;
+                    mediaImage->mPlane[mediaImage->Y].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = 1;
+                    mediaImage->mPlane[mediaImage->Y].mVertSubsampling = 1;
+
+                    mediaImage->mPlane[mediaImage->U].mOffset = stride * vStride;
+                    mediaImage->mPlane[mediaImage->U].mColInc = 4;
+                    mediaImage->mPlane[mediaImage->U].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->U].mHorizSubsampling = 2;
+                    mediaImage->mPlane[mediaImage->U].mVertSubsampling = 2;
+
+                    mediaImage->mPlane[mediaImage->V].mOffset = stride * vStride + 2;
+                    mediaImage->mPlane[mediaImage->V].mColInc = 4;
+                    mediaImage->mPlane[mediaImage->V].mRowInc = stride;
+                    mediaImage->mPlane[mediaImage->V].mHorizSubsampling = 2;
+                    mediaImage->mPlane[mediaImage->V].mVertSubsampling = 2;
+                    if (tryWrapping) {
+                        tryWrapping = yPlane.allocatedDepth == 16
+                                && uPlane.allocatedDepth == 16
+                                && vPlane.allocatedDepth == 16
+                                && yPlane.bitDepth == 10
+                                && uPlane.bitDepth == 10
+                                && vPlane.bitDepth == 10
+                                && yPlane.rightShift == 6
+                                && uPlane.rightShift == 6
+                                && vPlane.rightShift == 6
+                                && yPlane.rowSampling == 1 && yPlane.colSampling == 1
+                                && uPlane.rowSampling == 2 && uPlane.colSampling == 2
+                                && vPlane.rowSampling == 2 && vPlane.colSampling == 2
+                                && yPlane.colInc == 2
+                                && uPlane.colInc == 4
+                                && vPlane.colInc == 4
+                                && yPlane.rowInc == uPlane.rowInc
+                                && yPlane.rowInc == vPlane.rowInc;
+                    }
+                    break;
+
+                default: {
+                    // default to fully planar format --- this will be overridden if wrapping
+                    // TODO: keep interleaved format
+                    int32_t colInc = divUp(mAllocatedDepth, 8u);
+                    int32_t rowInc = stride * colInc / yPlane.colSampling;
+                    mediaImage->mPlane[mediaImage->Y].mOffset = 0;
+                    mediaImage->mPlane[mediaImage->Y].mColInc = colInc;
+                    mediaImage->mPlane[mediaImage->Y].mRowInc = rowInc;
+                    mediaImage->mPlane[mediaImage->Y].mHorizSubsampling = yPlane.colSampling;
+                    mediaImage->mPlane[mediaImage->Y].mVertSubsampling = yPlane.rowSampling;
+                    int32_t offset = rowInc * vStride / yPlane.rowSampling;
+
+                    rowInc = stride * colInc / uPlane.colSampling;
+                    mediaImage->mPlane[mediaImage->U].mOffset = offset;
+                    mediaImage->mPlane[mediaImage->U].mColInc = colInc;
+                    mediaImage->mPlane[mediaImage->U].mRowInc = rowInc;
+                    mediaImage->mPlane[mediaImage->U].mHorizSubsampling = uPlane.colSampling;
+                    mediaImage->mPlane[mediaImage->U].mVertSubsampling = uPlane.rowSampling;
+                    offset += rowInc * vStride / uPlane.rowSampling;
+
+                    rowInc = stride * colInc / vPlane.colSampling;
+                    mediaImage->mPlane[mediaImage->V].mOffset = offset;
+                    mediaImage->mPlane[mediaImage->V].mColInc = colInc;
+                    mediaImage->mPlane[mediaImage->V].mRowInc = rowInc;
+                    mediaImage->mPlane[mediaImage->V].mHorizSubsampling = vPlane.colSampling;
+                    mediaImage->mPlane[mediaImage->V].mVertSubsampling = vPlane.rowSampling;
+                    break;
+                }
+            }
+            break;
+        }
+
+        case C2PlanarLayout::TYPE_YUVA:
+            ALOGD("Converter: unrecognized color format "
+                    "(client %d component %d) for YUVA layout",
+                    mClientColorFormat, mComponentColorFormat);
+            mInitCheck = NO_INIT;
+            return;
+        case C2PlanarLayout::TYPE_RGB:
+            mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGB;
+            // TODO: support MediaImage layout
+            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:
+            mediaImage->mType = MediaImage2::MEDIA_IMAGE_TYPE_RGBA;
+            // TODO: support MediaImage layout
+            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) {
+                const C2PlaneInfo &plane = layout.planes[0];
+                if (plane.colInc < 0 || plane.rowInc < 0) {
+                    // Copy-only if we have negative colInc/rowInc
+                    tryWrapping = false;
+                }
+                mediaImage->mPlane[0].mOffset = 0;
+                mediaImage->mPlane[0].mColInc = std::abs(plane.colInc);
+                mediaImage->mPlane[0].mRowInc = std::abs(plane.rowInc);
+                mediaImage->mPlane[0].mHorizSubsampling = plane.colSampling;
+                mediaImage->mPlane[0].mVertSubsampling = plane.rowSampling;
+            } else {
+                ALOGD("Converter: unrecognized layout: color format (client %d component %d)",
+                        mClientColorFormat, mComponentColorFormat);
+                mInitCheck = NO_INIT;
+                return;
+            }
+            break;
+    }
+    if (tryWrapping) {
+        // try to map directly. check if the planes are near one another
+        const uint8_t *minPtr = mView.data()[0];
+        const uint8_t *maxPtr = mView.data()[0];
+        int32_t planeSize = 0;
+        for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+            const C2PlaneInfo &plane = layout.planes[i];
+            int64_t planeStride = std::abs(plane.rowInc / plane.colInc);
+            ssize_t minOffset = plane.minOffset(
+                    mWidth / plane.colSampling, mHeight / plane.rowSampling);
+            ssize_t maxOffset = plane.maxOffset(
+                    mWidth / plane.colSampling, mHeight / plane.rowSampling);
+            if (minPtr > mView.data()[i] + minOffset) {
+                minPtr = mView.data()[i] + minOffset;
+            }
+            if (maxPtr < mView.data()[i] + maxOffset) {
+                maxPtr = mView.data()[i] + maxOffset;
+            }
+            planeSize += planeStride * divUp(mAllocatedDepth, 8u)
+                    * align(mHeight, 64) / plane.rowSampling;
+        }
+
+        if (minPtr == mView.data()[0] && (maxPtr - minPtr) <= planeSize) {
+            // FIXME: this is risky as reading/writing data out of bound results
+            //        in an undefined behavior, but gralloc does assume a
+            //        contiguous mapping
+            for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+                const C2PlaneInfo &plane = layout.planes[i];
+                mediaImage->mPlane[i].mOffset = mView.data()[i] - minPtr;
+                mediaImage->mPlane[i].mColInc = plane.colInc;
+                mediaImage->mPlane[i].mRowInc = plane.rowInc;
+                mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
+                mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
+            }
+            mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr);
+            ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
+        }
+    }
+    mediaImage->mNumPlanes = layout.numPlanes;
+    mediaImage->mWidth = view.crop().width;
+    mediaImage->mHeight = view.crop().height;
+    mediaImage->mBitDepth = bitDepth;
+    mediaImage->mBitDepthAllocated = mAllocatedDepth;
+
+    uint32_t bufferSize = 0;
+    for (uint32_t i = 0; i < layout.numPlanes; ++i) {
+        const C2PlaneInfo &plane = layout.planes[i];
+        if (plane.allocatedDepth < plane.bitDepth
+                || plane.rightShift != plane.allocatedDepth - plane.bitDepth) {
+            ALOGD("rightShift value of %u unsupported", plane.rightShift);
+            mInitCheck = BAD_VALUE;
+            return;
+        }
+        if (plane.allocatedDepth > 8 && plane.endianness != C2PlaneInfo::NATIVE) {
+            ALOGD("endianness value of %u unsupported", plane.endianness);
+            mInitCheck = BAD_VALUE;
+            return;
+        }
+        if (plane.allocatedDepth != mAllocatedDepth || plane.bitDepth != bitDepth) {
+            ALOGD("different allocatedDepth/bitDepth per plane unsupported");
+            mInitCheck = BAD_VALUE;
+            return;
+        }
+        // stride is in bytes
+        bufferSize += stride * vStride / plane.rowSampling / plane.colSampling;
+    }
+
+    mBackBufferSize = bufferSize;
+    mInitCheck = OK;
+}
+
+status_t GraphicView2MediaImageConverter::initCheck() const { return mInitCheck; }
+
+uint32_t GraphicView2MediaImageConverter::backBufferSize() const { return mBackBufferSize; }
+
+sp<ABuffer> GraphicView2MediaImageConverter::wrap() const {
+    if (mBackBuffer == nullptr) {
+        return mWrapped;
+    }
+    return nullptr;
+}
+
+bool GraphicView2MediaImageConverter::setBackBuffer(const sp<ABuffer> &backBuffer) {
+    if (backBuffer == nullptr) {
+        return false;
+    }
+    if (backBuffer->capacity() < mBackBufferSize) {
+        return false;
+    }
+    backBuffer->setRange(0, mBackBufferSize);
+    mBackBuffer = backBuffer;
+    return true;
+}
+
+status_t GraphicView2MediaImageConverter::copyToMediaImage() {
+    ATRACE_CALL();
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+    return ImageCopy(mBackBuffer->base(), getMediaImage(), mView);
+}
+
+const sp<ABuffer> &GraphicView2MediaImageConverter::imageData() const { return mMediaImage; }
+
+MediaImage2 *GraphicView2MediaImageConverter::getMediaImage() {
+    return (MediaImage2 *)mMediaImage->base();
+}
+
 }  // namespace android
diff --git a/media/codec2/sfplugin/utils/Codec2BufferUtils.h b/media/codec2/sfplugin/utils/Codec2BufferUtils.h
index 6b0ba7f..8daf3d8 100644
--- a/media/codec2/sfplugin/utils/Codec2BufferUtils.h
+++ b/media/codec2/sfplugin/utils/Codec2BufferUtils.h
@@ -22,6 +22,7 @@
 #include <C2ParamDef.h>
 
 #include <media/hardware/VideoAPI.h>
+#include <utils/StrongPointer.h>
 #include <utils/Errors.h>
 
 namespace android {
@@ -194,6 +195,61 @@
     std::shared_ptr<Impl> mImpl;
 };
 
+struct ABuffer;
+struct AMessage;
+
+class GraphicView2MediaImageConverter {
+public:
+    /**
+     * Creates a C2GraphicView <=> MediaImage converter
+     *
+     * \param view C2GraphicView object
+     * \param format buffer format
+     * \param copy whether the converter is used for copy or not
+     */
+    GraphicView2MediaImageConverter(
+            const C2GraphicView &view, const sp<AMessage> &format, bool copy);
+
+    status_t initCheck() const;
+
+    uint32_t backBufferSize() const;
+
+    /**
+     * Wrap C2GraphicView using a MediaImage2. Note that if not wrapped, the content is not mapped
+     * in this function --- the caller should use CopyGraphicView2MediaImage() function to copy the
+     * data into a backing buffer explicitly.
+     *
+     * \return media buffer. This is null if wrapping failed.
+     */
+    sp<ABuffer> wrap() const;
+
+    bool setBackBuffer(const sp<ABuffer> &backBuffer);
+
+    /**
+     * Copy C2GraphicView to MediaImage2.
+     */
+    status_t copyToMediaImage();
+
+    const sp<ABuffer> &imageData() const;
+
+private:
+    status_t mInitCheck;
+
+    const C2GraphicView mView;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    int32_t mClientColorFormat;  ///< SDK color format for MediaImage
+    int32_t mComponentColorFormat;  ///< SDK color format from component
+    sp<ABuffer> mWrapped;  ///< wrapped buffer (if we can map C2Buffer to an ABuffer)
+    uint32_t mAllocatedDepth;
+    uint32_t mBackBufferSize;
+    sp<ABuffer> mMediaImage;
+
+    sp<ABuffer> mBackBuffer;    ///< backing buffer if we have to copy C2Buffer <=> ABuffer
+
+    MediaImage2 *getMediaImage();
+};
+
 } // namespace android
 
 #endif  // CODEC2_BUFFER_UTILS_H_
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 7b9b80d..bff953d 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -1311,8 +1311,7 @@
                 for (size_t planeIx = 0; planeIx < mLayout.numPlanes; ++planeIx) {
                     const uint32_t colSampling = mLayout.planes[planeIx].colSampling;
                     const uint32_t rowSampling = mLayout.planes[planeIx].rowSampling;
-                    if (crop.left % colSampling || crop.right() % colSampling
-                            || crop.top % rowSampling || crop.bottom() % rowSampling) {
+                    if (crop.left % colSampling || crop.top % rowSampling) {
                         // cannot calculate data pointer
                         mImpl->getAllocation()->unmap(mData, crop, nullptr);
                         memset(&mLayout, 0, sizeof(mLayout));
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index 4b417a7..add28e0 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -36,9 +36,6 @@
     symbol_file: "src/libaaudio.map.txt",
     first_version: "26",
     unversioned_until: "current",
-    export_header_libs: [
-        "libAAudio_headers",
-    ],
 }
 
 cc_library_headers {
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index 5785537..61204ae 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -158,6 +158,7 @@
         "framework-permission-aidl-cpp",
         "libbinder",
         "libmediametrics",
+        "libmediautils",
         "spatializer-aidl-cpp",
     ],
 
@@ -358,8 +359,6 @@
         "aidl/android/media/AudioMixerBehavior.aidl",
         "aidl/android/media/AudioOffloadMode.aidl",
         "aidl/android/media/AudioPolicyDeviceState.aidl",
-        "aidl/android/media/AudioPolicyForceUse.aidl",
-        "aidl/android/media/AudioPolicyForcedConfig.aidl",
         "aidl/android/media/AudioProductStrategy.aidl",
         "aidl/android/media/AudioVolumeGroup.aidl",
         "aidl/android/media/DeviceRole.aidl",
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f729e1b..a1d5b2b 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -79,6 +79,17 @@
     return NO_ERROR;
 }
 
+status_t AudioRecord::logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage,
+                                                const std::string& func) {
+    if (status != NO_ERROR) {
+        if (!func.empty()) mMediaMetrics.markError(status, func.c_str());
+        ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
+        reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
+    }
+    mStatus = status;
+    return mStatus;
+}
+
 // ---------------------------------------------------------------------------
 
 void AudioRecord::MediaMetrics::gather(const AudioRecord *record)
@@ -246,13 +257,28 @@
     if (pid == -1 || (callingPid != myPid)) {
         adjPid = callingPid;
     }
-    mClientAttributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(adjPid));
-
+    auto clientAttributionSourcePid = legacy2aidl_pid_t_int32_t(adjPid);
+    if (!clientAttributionSourcePid.ok()) {
+        return logIfErrorAndReturnStatus(BAD_VALUE,
+                                         StringPrintf("%s: received invalid client attribution "
+                                                      "source pid, pid: %d, sessionId: %d",
+                                                      __func__, pid, sessionId),
+                                         __func__);
+    }
+    mClientAttributionSource.pid = clientAttributionSourcePid.value();
     uid_t adjUid = uid;
     if (uid == -1 || (callingPid != myPid)) {
         adjUid = IPCThreadState::self()->getCallingUid();
     }
-    mClientAttributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(adjUid));
+    auto clientAttributionSourceUid = legacy2aidl_uid_t_int32_t(adjUid);
+    if (!clientAttributionSourceUid.ok()) {
+        return logIfErrorAndReturnStatus(BAD_VALUE,
+                                         StringPrintf("%s: received invalid client attribution "
+                                                      "source uid, pid: %d, session id: %d",
+                                                      __func__, pid, sessionId),
+                                         __func__);
+    }
+    mClientAttributionSource.uid = clientAttributionSourceUid.value();
 
     mTracker.reset(new RecordingActivityTracker());
 
@@ -261,7 +287,6 @@
     mSelectedMicFieldDimension = microphoneFieldDimension;
     mMaxSharedAudioHistoryMs = maxSharedAudioHistoryMs;
 
-    std::string errorMessage;
     // Copy the state variables early so they are available for error reporting.
     if (pAttributes == nullptr) {
         mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
@@ -304,38 +329,48 @@
         break;
     case TRANSFER_CALLBACK:
         if (callback == nullptr) {
-            errorMessage = StringPrintf(
-                    "%s: Transfer type TRANSFER_CALLBACK but callback == nullptr", __func__);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s: Transfer type TRANSFER_CALLBACK but callback == nullptr, "
+                                 "pid: %d, session id: %d",
+                                 __func__, pid, sessionId),
+                    __func__);
         }
         break;
     case TRANSFER_OBTAIN:
     case TRANSFER_SYNC:
         break;
     default:
-        errorMessage = StringPrintf("%s: Invalid transfer type %d", __func__, mTransfer);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE,
+                StringPrintf("%s: Invalid transfer type %d, pid: %d, session id: %d", __func__,
+                             mTransfer, pid, sessionId),
+                __func__);
     }
 
     // invariant that mAudioRecord != 0 is true only after set() returns successfully
     if (mAudioRecord != 0) {
-        errorMessage = StringPrintf("%s: Track already in use", __func__);
-        status = INVALID_OPERATION;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                INVALID_OPERATION,
+                StringPrintf("%s: Track already in use, pid: %d, session id: %d", __func__, pid,
+                             sessionId),
+                __func__);
     }
 
     if (!audio_is_valid_format(mFormat)) {
-        errorMessage = StringPrintf("%s: Format %#x is not valid", __func__, mFormat);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE,
+                StringPrintf("%s: Format %#x is not valid, pid: %d, session id: %d", __func__,
+                             mFormat, pid, sessionId),
+                __func__);
     }
 
     if (!audio_is_input_channel(mChannelMask)) {
-        errorMessage = StringPrintf("%s: Invalid channel mask %#x", __func__, mChannelMask);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE,
+                StringPrintf("%s: Invalid channel mask %#x, pid: %d, session id: %d", __func__,
+                             mChannelMask, pid, sessionId),
+                __func__);
     }
 
     mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
@@ -369,7 +404,8 @@
             mAudioRecordThread.clear();
         }
         // bypass error message to avoid logging twice (createRecord_l logs the error).
-        goto exit;
+        mStatus = status;
+        return mStatus;
     }
 
     // TODO: add audio hardware input latency here
@@ -385,15 +421,7 @@
     mFramesRead = 0;
     mFramesReadServerOffset = 0;
 
-error:
-    if (status != NO_ERROR) {
-        mMediaMetrics.markError(status, __FUNCTION__);
-        ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
-        reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
-    }
-exit:
-    mStatus = status;
-    return status;
+    return logIfErrorAndReturnStatus(status, "", __func__);
 }
 
 // -------------------------------------------------------------------------
@@ -783,12 +811,10 @@
     status_t status;
     static const int32_t kMaxCreateAttempts = 3;
     int32_t remainingAttempts = kMaxCreateAttempts;
-    std::string errorMessage;
 
     if (audioFlinger == 0) {
-        errorMessage = StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId);
-        status = NO_INIT;
-        goto exit;
+        return logIfErrorAndReturnStatus(
+                NO_INIT, StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId), "");
     }
 
     // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
@@ -846,16 +872,34 @@
 
     do {
         media::CreateRecordResponse response;
-        status = audioFlinger->createRecord(VALUE_OR_FATAL(input.toAidl()), response);
-        output = VALUE_OR_FATAL(IAudioFlinger::CreateRecordOutput::fromAidl(response));
+        auto aidlInput = input.toAidl();
+        if (!aidlInput.ok()) {
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s(%d): Could not create record due to invalid input", __func__,
+                                 mPortId),
+                    "");
+        }
+        status = audioFlinger->createRecord(aidlInput.value(), response);
+
+        auto recordOutput = IAudioFlinger::CreateRecordOutput::fromAidl(response);
+        if (!recordOutput.ok()) {
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s(%d): Could not create record output due to invalid response",
+                                 __func__, mPortId),
+                    "");
+        }
+        output = recordOutput.value();
         if (status == NO_ERROR) {
             break;
         }
         if (status != FAILED_TRANSACTION || --remainingAttempts <= 0) {
-            errorMessage = StringPrintf(
-                    "%s(%d): AudioFlinger could not create record track, status: %d",
-                    __func__, mPortId, status);
-            goto exit;
+            return logIfErrorAndReturnStatus(
+                    status,
+                    StringPrintf("%s(%d): AudioFlinger could not create record track, status: %d",
+                                 __func__, mPortId, status),
+                    "");
         }
         // FAILED_TRANSACTION happens under very specific conditions causing a state mismatch
         // between audio policy manager and audio flinger during the input stream open sequence
@@ -890,9 +934,9 @@
     mHalFormat = output.halConfig.format;
 
     if (output.cblk == 0) {
-        errorMessage = StringPrintf("%s(%d): Could not get control block", __func__, mPortId);
-        status = NO_INIT;
-        goto exit;
+        return logIfErrorAndReturnStatus(
+                NO_INIT, StringPrintf("%s(%d): Could not get control block", __func__, mPortId),
+                "");
     }
     // TODO: Using unsecurePointer() has some associated security pitfalls
     //       (see declaration for details).
@@ -900,10 +944,9 @@
     //       issue (e.g. by copying).
     iMemPointer = output.cblk ->unsecurePointer();
     if (iMemPointer == NULL) {
-        errorMessage = StringPrintf(
-                "%s(%d): Could not get control block pointer", __func__, mPortId);
-        status = NO_INIT;
-        goto exit;
+        return logIfErrorAndReturnStatus(
+                NO_INIT,
+                StringPrintf("%s(%d): Could not get control block pointer", __func__, mPortId), "");
     }
     cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
 
@@ -920,10 +963,9 @@
         //       issue (e.g. by copying).
         buffers = output.buffers->unsecurePointer();
         if (buffers == NULL) {
-            errorMessage = StringPrintf(
-                    "%s(%d): Could not get buffer pointer", __func__, mPortId);
-            status = NO_INIT;
-            goto exit;
+            return logIfErrorAndReturnStatus(
+                    NO_INIT,
+                    StringPrintf("%s(%d): Could not get buffer pointer", __func__, mPortId), "");
         }
     }
 
@@ -1015,15 +1057,8 @@
         .set(AMEDIAMETRICS_PROP_SELECTEDMICFIELDDIRECTION, (double)mSelectedMicFieldDimension)
         .record();
 
-exit:
-    if (status != NO_ERROR) {
-        ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
-        reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
-    }
-
-    mStatus = status;
     // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
-    return status;
+    return logIfErrorAndReturnStatus(status, "", "");
 }
 
 // Report error associated with the event and some configuration details.
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 3f4fcfd..85f4a86 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -60,6 +60,8 @@
 using media::audio::common::AudioMMapPolicyInfo;
 using media::audio::common::AudioMMapPolicyType;
 using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioPolicyForceUse;
+using media::audio::common::AudioPolicyForcedConfig;
 using media::audio::common::AudioSource;
 using media::audio::common::AudioStreamType;
 using media::audio::common::AudioUsage;
@@ -1059,9 +1061,9 @@
     if (aps == 0) return AUDIO_POLICY_FORCE_NONE;
 
     auto result = [&]() -> ConversionResult<audio_policy_forced_cfg_t> {
-        media::AudioPolicyForceUse usageAidl = VALUE_OR_RETURN(
+        AudioPolicyForceUse usageAidl = VALUE_OR_RETURN(
                 legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(usage));
-        media::AudioPolicyForcedConfig configAidl;
+        AudioPolicyForcedConfig configAidl;
         RETURN_IF_ERROR(statusTFromBinderStatus(
                 aps->getForceUse(usageAidl, &configAidl)));
         return aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(configAidl);
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index e2386ca..f92103b 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -188,6 +188,14 @@
     return result.value_or(false);
 }
 
+status_t AudioTrack::logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage) {
+    if (status != NO_ERROR) {
+        ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
+        reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
+    }
+    mStatus = status;
+    return mStatus;
+}
 // ---------------------------------------------------------------------------
 
 void AudioTrack::MediaMetrics::gather(const AudioTrack *track)
@@ -365,6 +373,10 @@
                 mSessionId, IPCThreadState::self()->getCallingPid(), clientPid);
         AudioSystem::releaseAudioSessionId(mSessionId, clientPid);
     }
+
+    if (mOutput != AUDIO_IO_HANDLE_NONE) {
+        AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
+    }
 }
 
 void AudioTrack::stopAndJoinCallbacks() {
@@ -413,9 +425,16 @@
     uint32_t channelCount;
     pid_t callingPid;
     pid_t myPid;
-    uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
-    pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(attributionSource.pid));
-    std::string errorMessage;
+    auto uid = aidl2legacy_int32_t_uid_t(attributionSource.uid);
+    auto pid = aidl2legacy_int32_t_pid_t(attributionSource.pid);
+    if (!uid.ok()) {
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE, StringPrintf("%s: received invalid attribution source uid", __func__));
+    }
+    if (!pid.ok()) {
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE, StringPrintf("%s: received invalid attribution source pid", __func__));
+    }
     // Note mPortId is not valid until the track is created, so omit mPortId in ALOG for set.
     ALOGV("%s(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
           "flags %#x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
@@ -486,34 +505,33 @@
     case TRANSFER_CALLBACK:
     case TRANSFER_SYNC_NOTIF_CALLBACK:
         if (callback == nullptr || sharedBuffer != 0) {
-            errorMessage = StringPrintf(
-                    "%s: Transfer type %s but callback == nullptr || sharedBuffer != 0",
-                    convertTransferToText(transferType), __func__);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf(
+                            "%s: Transfer type %s but callback == nullptr || sharedBuffer != 0",
+                            convertTransferToText(transferType), __func__));
         }
         break;
     case TRANSFER_OBTAIN:
     case TRANSFER_SYNC:
         if (sharedBuffer != 0) {
-            errorMessage = StringPrintf(
-                    "%s: Transfer type TRANSFER_OBTAIN but sharedBuffer != 0", __func__);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s: Transfer type TRANSFER_OBTAIN but sharedBuffer != 0",
+                                 __func__));
         }
         break;
     case TRANSFER_SHARED:
         if (sharedBuffer == 0) {
-            errorMessage = StringPrintf(
-                    "%s: Transfer type TRANSFER_SHARED but sharedBuffer == 0", __func__);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s: Transfer type TRANSFER_SHARED but sharedBuffer == 0",
+                                 __func__));
         }
         break;
     default:
-        errorMessage = StringPrintf("%s: Invalid transfer type %d", __func__, transferType);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE, StringPrintf("%s: Invalid transfer type %d", __func__, transferType));
     }
     mSharedBuffer = sharedBuffer;
     mTransfer = transferType;
@@ -524,9 +542,8 @@
 
     // invariant that mAudioTrack != 0 is true only after set() returns successfully
     if (mAudioTrack != 0) {
-        errorMessage = StringPrintf("%s: Track already in use", __func__);
-        status = INVALID_OPERATION;
-        goto error;
+        return logIfErrorAndReturnStatus(INVALID_OPERATION,
+                                         StringPrintf("%s: Track already in use", __func__));
     }
 
     // handle default values first.
@@ -535,9 +552,8 @@
     }
     if (pAttributes == NULL) {
         if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
-            errorMessage = StringPrintf("%s: Invalid stream type %d", __func__, streamType);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE, StringPrintf("%s: Invalid stream type %d", __func__, streamType));
         }
         mOriginalStreamType = streamType;
     } else {
@@ -546,15 +562,13 @@
 
     // validate parameters
     if (!audio_is_valid_format(format)) {
-        errorMessage = StringPrintf("%s: Invalid format %#x", __func__, format);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(BAD_VALUE,
+                                         StringPrintf("%s: Invalid format %#x", __func__, format));
     }
 
     if (!audio_is_output_channel(channelMask)) {
-        errorMessage = StringPrintf("%s: Invalid channel mask %#x",  __func__, channelMask);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE, StringPrintf("%s: Invalid channel mask %#x", __func__, channelMask));
     }
     channelCount = audio_channel_count_from_out_mask(channelMask);
     mChannelCount = channelCount;
@@ -569,10 +583,9 @@
 
     // sampling rate must be specified for direct outputs
     if (sampleRate == 0 && (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
-        errorMessage = StringPrintf(
-                "%s: sample rate must be specified for direct outputs", __func__);
-        status = BAD_VALUE;
-        goto error;
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE,
+                StringPrintf("%s: sample rate must be specified for direct outputs", __func__));
     }
     // 1.0 <= mMaxRequiredSpeed <= AUDIO_TIMESTRETCH_SPEED_MAX
     mMaxRequiredSpeed = min(max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
@@ -600,17 +613,16 @@
         mNotificationsPerBufferReq = 0;
     } else {
         if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
-            errorMessage = StringPrintf(
-                    "%s: notificationFrames=%d not permitted for non-fast track",
-                    __func__, notificationFrames);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s: notificationFrames=%d not permitted for non-fast track",
+                                 __func__, notificationFrames));
         }
         if (frameCount > 0) {
-            ALOGE("%s(): notificationFrames=%d not permitted with non-zero frameCount=%zu",
-                    __func__, notificationFrames, frameCount);
-            status = BAD_VALUE;
-            goto error;
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE, StringPrintf("%s(): notificationFrames=%d not permitted "
+                                            "with non-zero frameCount=%zu",
+                                            __func__, notificationFrames, frameCount));
         }
         mNotificationFramesReq = 0;
         const uint32_t minNotificationsPerBuffer = 1;
@@ -627,12 +639,24 @@
     mClientAttributionSource = AttributionSourceState(attributionSource);
     callingPid = IPCThreadState::self()->getCallingPid();
     myPid = getpid();
-    if (uid == -1 || (callingPid != myPid)) {
-        mClientAttributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(
-            IPCThreadState::self()->getCallingUid()));
+    if (uid.value() == -1 || (callingPid != myPid)) {
+        auto clientAttributionSourceUid =
+                legacy2aidl_uid_t_int32_t(IPCThreadState::self()->getCallingUid());
+        if (!clientAttributionSourceUid.ok()) {
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s: received invalid client attribution source uid", __func__));
+        }
+        mClientAttributionSource.uid = clientAttributionSourceUid.value();
     }
-    if (pid == (pid_t)-1 || (callingPid != myPid)) {
-        mClientAttributionSource.pid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(callingPid));
+    if (pid.value() == (pid_t)-1 || (callingPid != myPid)) {
+        auto clientAttributionSourcePid = legacy2aidl_uid_t_int32_t(callingPid);
+        if (!clientAttributionSourcePid.ok()) {
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s: received invalid client attribution source pid", __func__));
+        }
+        mClientAttributionSource.pid = clientAttributionSourcePid.value();
     }
     mAuxEffectId = 0;
     mCallback = callback;
@@ -655,7 +679,8 @@
             mAudioTrackThread.clear();
         }
         // We do not goto error to prevent double-logging errors.
-        goto exit;
+        mStatus = status;
+        return mStatus;
     }
 
     mLoopCount = 0;
@@ -670,7 +695,7 @@
     mReleased = 0;
     mStartNs = 0;
     mStartFromZeroUs = 0;
-    AudioSystem::acquireAudioSessionId(mSessionId, pid, uid);
+    AudioSystem::acquireAudioSessionId(mSessionId, pid.value(), uid.value());
     mSequence = 1;
     mObservedSequence = mSequence;
     mInUnderrun = false;
@@ -688,15 +713,7 @@
     mFramesWrittenAtRestore = -1; // -1 is a unique initializer.
     mVolumeHandler = new media::VolumeHandler();
 
-error:
-    if (status != NO_ERROR) {
-        ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
-        reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
-    }
-    // fall through
-exit:
-    mStatus = status;
-    return status;
+    return logIfErrorAndReturnStatus(status, "");
 }
 
 
@@ -723,8 +740,22 @@
         audio_port_handle_t selectedDeviceId)
 {
     AttributionSourceState attributionSource;
-    attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(uid));
-    attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(pid));
+    auto attributionSourceUid = legacy2aidl_uid_t_int32_t(uid);
+    if (!attributionSourceUid.ok()) {
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE,
+                StringPrintf("%s: received invalid attribution source uid, uid: %d, session id: %d",
+                             __func__, uid, sessionId));
+    }
+    attributionSource.uid = attributionSourceUid.value();
+    auto attributionSourcePid = legacy2aidl_pid_t_int32_t(pid);
+    if (!attributionSourcePid.ok()) {
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE,
+                StringPrintf("%s: received invalid attribution source pid, pid: %d, sessionId: %d",
+                             __func__, pid, sessionId));
+    }
+    attributionSource.pid = attributionSourcePid.value();
     attributionSource.token = sp<BBinder>::make();
     if (callback) {
         mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
@@ -1792,15 +1823,11 @@
 status_t AudioTrack::createTrack_l()
 {
     status_t status;
-    bool callbackAdded = false;
-    std::string errorMessage;
 
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
     if (audioFlinger == 0) {
-        errorMessage = StringPrintf("%s(%d): Could not get audioflinger",
-                __func__, mPortId);
-        status = DEAD_OBJECT;
-        goto exit;
+        return logIfErrorAndReturnStatus(
+                DEAD_OBJECT, StringPrintf("%s(%d): Could not get audioflinger", __func__, mPortId));
     }
 
     {
@@ -1868,21 +1895,31 @@
     input.audioTrackCallback = mAudioTrackCallback;
 
     media::CreateTrackResponse response;
-    status = audioFlinger->createTrack(VALUE_OR_FATAL(input.toAidl()), response);
+    auto aidlInput = input.toAidl();
+    if (!aidlInput.ok()) {
+        return logIfErrorAndReturnStatus(
+                BAD_VALUE, StringPrintf("%s(%d): Could not create track due to invalid input",
+                                        __func__, mPortId));
+    }
+    status = audioFlinger->createTrack(aidlInput.value(), response);
 
     IAudioFlinger::CreateTrackOutput output{};
     if (status == NO_ERROR) {
-        output = VALUE_OR_FATAL(IAudioFlinger::CreateTrackOutput::fromAidl(response));
+        auto trackOutput = IAudioFlinger::CreateTrackOutput::fromAidl(response);
+        if (!trackOutput.ok()) {
+            return logIfErrorAndReturnStatus(
+                    BAD_VALUE,
+                    StringPrintf("%s(%d): Could not create track output due to invalid response",
+                                 __func__, mPortId));
+        }
+        output = trackOutput.value();
     }
 
     if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
-        errorMessage = StringPrintf(
-                "%s(%d): AudioFlinger could not create track, status: %d output %d",
-                __func__, mPortId, status, output.outputId);
-        if (status == NO_ERROR) {
-            status = INVALID_OPERATION; // device not ready
-        }
-        goto exit;
+        return logIfErrorAndReturnStatus(
+                status == NO_ERROR ? INVALID_OPERATION : status,  // device not ready
+                StringPrintf("%s(%d): AudioFlinger could not create track, status: %d output %d",
+                             __func__, mPortId, status, output.outputId));
     }
     ALOG_ASSERT(output.audioTrack != 0);
 
@@ -1912,22 +1949,22 @@
     // FIXME compare to AudioRecord
     std::optional<media::SharedFileRegion> sfr;
     output.audioTrack->getCblk(&sfr);
-    sp<IMemory> iMem = VALUE_OR_FATAL(aidl2legacy_NullableSharedFileRegion_IMemory(sfr));
-    if (iMem == 0) {
-        errorMessage = StringPrintf("%s(%d): Could not get control block", __func__, mPortId);
-        status = FAILED_TRANSACTION;
-        goto exit;
+    auto iMemory = aidl2legacy_NullableSharedFileRegion_IMemory(sfr);
+    if (!iMemory.ok() || iMemory.value() == 0) {
+        return logIfErrorAndReturnStatus(
+                FAILED_TRANSACTION,
+                StringPrintf("%s(%d): Could not get control block", __func__, mPortId));
     }
+    sp<IMemory> iMem = iMemory.value();
     // TODO: Using unsecurePointer() has some associated security pitfalls
     //       (see declaration for details).
     //       Either document why it is safe in this case or address the
     //       issue (e.g. by copying).
     void *iMemPointer = iMem->unsecurePointer();
     if (iMemPointer == NULL) {
-        errorMessage = StringPrintf(
-                "%s(%d): Could not get control block pointer", __func__, mPortId);
-        status = FAILED_TRANSACTION;
-        goto exit;
+        return logIfErrorAndReturnStatus(
+                FAILED_TRANSACTION,
+                StringPrintf("%s(%d): Could not get control block pointer", __func__, mPortId));
     }
     // invariant that mAudioTrack != 0 is true only after set() returns successfully
     if (mAudioTrack != 0) {
@@ -1962,7 +1999,6 @@
             AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
         }
         AudioSystem::addAudioDeviceCallback(this, output.outputId, output.portId);
-        callbackAdded = true;
     }
 
     mPortId = output.portId;
@@ -1987,11 +2023,9 @@
         //       issue (e.g. by copying).
         buffers = mSharedBuffer->unsecurePointer();
         if (buffers == NULL) {
-            errorMessage = StringPrintf(
-                    "%s(%d): Could not get buffer pointer", __func__, mPortId);
-            ALOGE("%s", errorMessage.c_str());
-            status = FAILED_TRANSACTION;
-            goto exit;
+            return logIfErrorAndReturnStatus(
+                    FAILED_TRANSACTION,
+                    StringPrintf("%s(%d): Could not get buffer pointer", __func__, mPortId));
         }
     }
 
@@ -2088,19 +2122,8 @@
 
     }
 
-exit:
-    if (status != NO_ERROR) {
-        if (callbackAdded) {
-            // note: mOutput is always valid is callbackAdded is true
-            AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
-        }
-        ALOGE_IF(!errorMessage.empty(), "%s", errorMessage.c_str());
-        reportError(status, AMEDIAMETRICS_PROP_EVENT_VALUE_CREATE, errorMessage.c_str());
-    }
-    mStatus = status;
-
     // sp<IAudioTrack> track destructor will cause releaseOutput() to be called by AudioFlinger
-    return status;
+    return logIfErrorAndReturnStatus(status, "");
 }
 
 void AudioTrack::reportError(status_t status, const char *event, const char *message) const
@@ -3189,7 +3212,12 @@
         media::AudioTimestampInternal ts;
         mAudioTrack->getTimestamp(&ts, &status);
         if (status == OK) {
-            timestamp = VALUE_OR_FATAL(aidl2legacy_AudioTimestampInternal_AudioTimestamp(ts));
+            auto legacyTs = aidl2legacy_AudioTimestampInternal_AudioTimestamp(ts);
+            if (!legacyTs.ok()) {
+                return logIfErrorAndReturnStatus(
+                        BAD_VALUE, StringPrintf("%s: received invalid audio timestamp", __func__));
+            }
+            timestamp = legacyTs.value();
         }
     } else {
         // read timestamp from shared memory
diff --git a/media/libaudioclient/PolicyAidlConversion.cpp b/media/libaudioclient/PolicyAidlConversion.cpp
index 163a359..a414cb7 100644
--- a/media/libaudioclient/PolicyAidlConversion.cpp
+++ b/media/libaudioclient/PolicyAidlConversion.cpp
@@ -296,138 +296,6 @@
     return unexpected(BAD_VALUE);
 }
 
-ConversionResult<audio_policy_force_use_t>
-aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(media::AudioPolicyForceUse aidl) {
-    switch (aidl) {
-        case media::AudioPolicyForceUse::COMMUNICATION:
-            return AUDIO_POLICY_FORCE_FOR_COMMUNICATION;
-        case media::AudioPolicyForceUse::MEDIA:
-            return AUDIO_POLICY_FORCE_FOR_MEDIA;
-        case media::AudioPolicyForceUse::RECORD:
-            return AUDIO_POLICY_FORCE_FOR_RECORD;
-        case media::AudioPolicyForceUse::DOCK:
-            return AUDIO_POLICY_FORCE_FOR_DOCK;
-        case media::AudioPolicyForceUse::SYSTEM:
-            return AUDIO_POLICY_FORCE_FOR_SYSTEM;
-        case media::AudioPolicyForceUse::HDMI_SYSTEM_AUDIO:
-            return AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO;
-        case media::AudioPolicyForceUse::ENCODED_SURROUND:
-            return AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND;
-        case media::AudioPolicyForceUse::VIBRATE_RINGING:
-            return AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioPolicyForceUse>
-legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy) {
-    switch (legacy) {
-        case AUDIO_POLICY_FORCE_FOR_COMMUNICATION:
-            return media::AudioPolicyForceUse::COMMUNICATION;
-        case AUDIO_POLICY_FORCE_FOR_MEDIA:
-            return media::AudioPolicyForceUse::MEDIA;
-        case AUDIO_POLICY_FORCE_FOR_RECORD:
-            return media::AudioPolicyForceUse::RECORD;
-        case AUDIO_POLICY_FORCE_FOR_DOCK:
-            return media::AudioPolicyForceUse::DOCK;
-        case AUDIO_POLICY_FORCE_FOR_SYSTEM:
-            return media::AudioPolicyForceUse::SYSTEM;
-        case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
-            return media::AudioPolicyForceUse::HDMI_SYSTEM_AUDIO;
-        case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
-            return media::AudioPolicyForceUse::ENCODED_SURROUND;
-        case AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING:
-            return media::AudioPolicyForceUse::VIBRATE_RINGING;
-        case AUDIO_POLICY_FORCE_USE_CNT:
-            break;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_policy_forced_cfg_t>
-aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(media::AudioPolicyForcedConfig aidl) {
-    switch (aidl) {
-        case media::AudioPolicyForcedConfig::NONE:
-            return AUDIO_POLICY_FORCE_NONE;
-        case media::AudioPolicyForcedConfig::SPEAKER:
-            return AUDIO_POLICY_FORCE_SPEAKER;
-        case media::AudioPolicyForcedConfig::HEADPHONES:
-            return AUDIO_POLICY_FORCE_HEADPHONES;
-        case media::AudioPolicyForcedConfig::BT_SCO:
-            return AUDIO_POLICY_FORCE_BT_SCO;
-        case media::AudioPolicyForcedConfig::BT_A2DP:
-            return AUDIO_POLICY_FORCE_BT_A2DP;
-        case media::AudioPolicyForcedConfig::WIRED_ACCESSORY:
-            return AUDIO_POLICY_FORCE_WIRED_ACCESSORY;
-        case media::AudioPolicyForcedConfig::BT_CAR_DOCK:
-            return AUDIO_POLICY_FORCE_BT_CAR_DOCK;
-        case media::AudioPolicyForcedConfig::BT_DESK_DOCK:
-            return AUDIO_POLICY_FORCE_BT_DESK_DOCK;
-        case media::AudioPolicyForcedConfig::ANALOG_DOCK:
-            return AUDIO_POLICY_FORCE_ANALOG_DOCK;
-        case media::AudioPolicyForcedConfig::DIGITAL_DOCK:
-            return AUDIO_POLICY_FORCE_DIGITAL_DOCK;
-        case media::AudioPolicyForcedConfig::NO_BT_A2DP:
-            return AUDIO_POLICY_FORCE_NO_BT_A2DP;
-        case media::AudioPolicyForcedConfig::SYSTEM_ENFORCED:
-            return AUDIO_POLICY_FORCE_SYSTEM_ENFORCED;
-        case media::AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED:
-            return AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED;
-        case media::AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER:
-            return AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER;
-        case media::AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS:
-            return AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS;
-        case media::AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL:
-            return AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL;
-        case media::AudioPolicyForcedConfig::BT_BLE:
-            return AUDIO_POLICY_FORCE_BT_BLE;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioPolicyForcedConfig>
-legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy) {
-    switch (legacy) {
-        case AUDIO_POLICY_FORCE_NONE:
-            return media::AudioPolicyForcedConfig::NONE;
-        case AUDIO_POLICY_FORCE_SPEAKER:
-            return media::AudioPolicyForcedConfig::SPEAKER;
-        case AUDIO_POLICY_FORCE_HEADPHONES:
-            return media::AudioPolicyForcedConfig::HEADPHONES;
-        case AUDIO_POLICY_FORCE_BT_SCO:
-            return media::AudioPolicyForcedConfig::BT_SCO;
-        case AUDIO_POLICY_FORCE_BT_A2DP:
-            return media::AudioPolicyForcedConfig::BT_A2DP;
-        case AUDIO_POLICY_FORCE_WIRED_ACCESSORY:
-            return media::AudioPolicyForcedConfig::WIRED_ACCESSORY;
-        case AUDIO_POLICY_FORCE_BT_CAR_DOCK:
-            return media::AudioPolicyForcedConfig::BT_CAR_DOCK;
-        case AUDIO_POLICY_FORCE_BT_DESK_DOCK:
-            return media::AudioPolicyForcedConfig::BT_DESK_DOCK;
-        case AUDIO_POLICY_FORCE_ANALOG_DOCK:
-            return media::AudioPolicyForcedConfig::ANALOG_DOCK;
-        case AUDIO_POLICY_FORCE_DIGITAL_DOCK:
-            return media::AudioPolicyForcedConfig::DIGITAL_DOCK;
-        case AUDIO_POLICY_FORCE_NO_BT_A2DP:
-            return media::AudioPolicyForcedConfig::NO_BT_A2DP;
-        case AUDIO_POLICY_FORCE_SYSTEM_ENFORCED:
-            return media::AudioPolicyForcedConfig::SYSTEM_ENFORCED;
-        case AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED:
-            return media::AudioPolicyForcedConfig::HDMI_SYSTEM_AUDIO_ENFORCED;
-        case AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER:
-            return media::AudioPolicyForcedConfig::ENCODED_SURROUND_NEVER;
-        case AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS:
-            return media::AudioPolicyForcedConfig::ENCODED_SURROUND_ALWAYS;
-        case AUDIO_POLICY_FORCE_ENCODED_SURROUND_MANUAL:
-            return media::AudioPolicyForcedConfig::ENCODED_SURROUND_MANUAL;
-        case AUDIO_POLICY_FORCE_BT_BLE:
-            return media::AudioPolicyForcedConfig::BT_BLE;
-        case AUDIO_POLICY_FORCE_CFG_CNT:
-            break;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<device_role_t>
 aidl2legacy_DeviceRole_device_role_t(media::DeviceRole aidl) {
     switch (aidl) {
diff --git a/media/libaudioclient/TrackPlayerBase.cpp b/media/libaudioclient/TrackPlayerBase.cpp
index 4fc1c44..bc38251 100644
--- a/media/libaudioclient/TrackPlayerBase.cpp
+++ b/media/libaudioclient/TrackPlayerBase.cpp
@@ -38,12 +38,12 @@
                            player_type_t playerType, audio_usage_t usage,
                            audio_session_t sessionId) {
     PlayerBase::init(playerType, usage, sessionId);
-    mAudioTrack = pat;
-    if (mAudioTrack != 0) {
+    mAudioTrack.store(pat);
+    if (pat != 0) {
         mCallbackHandle = callback;
         mSelfAudioDeviceCallback = new SelfAudioDeviceCallback(*this);
-        mAudioTrack->addAudioDeviceCallback(mSelfAudioDeviceCallback);
-        mAudioTrack->setPlayerIId(mPIId); // set in PlayerBase::init().
+        pat->addAudioDeviceCallback(mSelfAudioDeviceCallback);
+        pat->setPlayerIId(mPIId);  // set in PlayerBase::init().
     }
 }
 
@@ -65,12 +65,15 @@
 }
 
 void TrackPlayerBase::doDestroy() {
-    if (mAudioTrack != 0) {
-        mAudioTrack->stop();
-        mAudioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
+    sp<AudioTrack> audioTrack = getAudioTrack();
+
+    // Note that there may still be another reference in post-unlock phase of SetPlayState
+    clearAudioTrack();
+
+    if (audioTrack != 0) {
+        audioTrack->stop();
+        audioTrack->removeAudioDeviceCallback(mSelfAudioDeviceCallback);
         mSelfAudioDeviceCallback.clear();
-        // Note that there may still be another reference in post-unlock phase of SetPlayState
-        mAudioTrack.clear();
     }
 }
 
@@ -87,16 +90,16 @@
 // Implementation of IPlayer
 status_t TrackPlayerBase::playerStart() {
     status_t status = NO_INIT;
-    if (mAudioTrack != 0) {
-        status = mAudioTrack->start();
+    if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
+        status = audioTrack->start();
     }
     return status;
 }
 
 status_t TrackPlayerBase::playerPause() {
     status_t status = NO_INIT;
-    if (mAudioTrack != 0) {
-        mAudioTrack->pause();
+    if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
+        audioTrack->pause();
         status = NO_ERROR;
     }
     return status;
@@ -105,8 +108,8 @@
 
 status_t TrackPlayerBase::playerStop() {
     status_t status = NO_INIT;
-    if (mAudioTrack != 0) {
-        mAudioTrack->stop();
+    if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
+        audioTrack->stop();
         status = NO_ERROR;
     }
     return status;
@@ -118,10 +121,10 @@
 
 status_t TrackPlayerBase::doSetVolume() {
     status_t status = NO_INIT;
-    if (mAudioTrack != 0) {
+    if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
         float tl = mPlayerVolumeL * mPanMultiplierL * mVolumeMultiplierL;
         float tr = mPlayerVolumeR * mPanMultiplierR * mVolumeMultiplierR;
-        mAudioTrack->setVolume(tl, tr);
+        audioTrack->setVolume(tl, tr);
         status = NO_ERROR;
     }
     return status;
@@ -140,10 +143,9 @@
     if (s != OK) {
         return binderStatusFromStatusT(s);
     }
-
-    if (mAudioTrack != 0) {
+    if (sp<AudioTrack> audioTrack = getAudioTrack(); audioTrack != 0) {
         ALOGD("TrackPlayerBase::applyVolumeShaper() from IPlayer");
-        VolumeShaper::Status status = mAudioTrack->applyVolumeShaper(spConfiguration, spOperation);
+        VolumeShaper::Status status = audioTrack->applyVolumeShaper(spConfiguration, spOperation);
         if (status < 0) { // a non-negative value is the volume shaper id.
             ALOGE("TrackPlayerBase::applyVolumeShaper() failed with status %d", status);
         }
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyForceUse.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyForceUse.aidl
deleted file mode 100644
index 9bb0605..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPolicyForceUse.aidl
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioPolicyForceUse {
-    COMMUNICATION = 0,
-    MEDIA = 1,
-    RECORD = 2,
-    DOCK = 3,
-    SYSTEM = 4,
-    HDMI_SYSTEM_AUDIO = 5,
-    ENCODED_SURROUND = 6,
-    VIBRATE_RINGING = 7,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPolicyForcedConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPolicyForcedConfig.aidl
deleted file mode 100644
index 111bb2f..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPolicyForcedConfig.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- */
-package android.media;
-
-/**
- * {@hide}
- */
-@Backing(type="int")
-enum AudioPolicyForcedConfig {
-    NONE = 0,
-    SPEAKER = 1,
-    HEADPHONES = 2,
-    BT_SCO = 3,
-    BT_A2DP = 4,
-    WIRED_ACCESSORY = 5,
-    BT_CAR_DOCK = 6,
-    BT_DESK_DOCK = 7,
-    ANALOG_DOCK = 8,
-    DIGITAL_DOCK = 9,
-    NO_BT_A2DP = 10, /* A2DP sink is not preferred to speaker or wired HS */
-    SYSTEM_ENFORCED = 11,
-    HDMI_SYSTEM_AUDIO_ENFORCED = 12,
-    ENCODED_SURROUND_NEVER = 13,
-    ENCODED_SURROUND_ALWAYS = 14,
-    ENCODED_SURROUND_MANUAL = 15,
-    BT_BLE = 16,
-}
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index ac42ea9..7f5e8e2 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -25,8 +25,6 @@
 import android.media.AudioOffloadMode;
 import android.media.AudioPatchFw;
 import android.media.AudioPolicyDeviceState;
-import android.media.AudioPolicyForcedConfig;
-import android.media.AudioPolicyForceUse;
 import android.media.AudioPortFw;
 import android.media.AudioPortConfigFw;
 import android.media.AudioPortRole;
@@ -49,6 +47,8 @@
 import android.media.audio.common.AudioDeviceDescription;
 import android.media.audio.common.AudioFormatDescription;
 import android.media.audio.common.AudioMode;
+import android.media.audio.common.AudioPolicyForcedConfig;
+import android.media.audio.common.AudioPolicyForceUse;
 import android.media.audio.common.AudioProfile;
 import android.media.audio.common.AudioOffloadInfo;
 import android.media.audio.common.AudioPort;
diff --git a/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl b/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
index ddda8bb..73610a8 100644
--- a/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
@@ -19,6 +19,7 @@
 import android.media.AudioPortFw;
 import android.media.audio.common.AudioConfig;
 import android.media.audio.common.AudioConfigBase;
+import android.media.audio.common.AudioAttributes;
 
 /**
  * {@hide}
@@ -32,4 +33,5 @@
     AudioPortFw device;
     /** Bitmask, indexed by AudioOutputFlag. */
     int flags;
+    AudioAttributes attributes;
 }
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
index 11955c9..61d5ccd 100644
--- a/media/libaudioclient/aidl/fuzzer/Android.bp
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -28,53 +28,20 @@
         "libcgrouprc_format",
         "libfakeservicemanager",
         "libjsoncpp",
-        "liblog",
-        "libmedia_helper",
         "libmediametricsservice",
         "libprocessgroup",
         "shared-file-region-aidl-cpp",
     ],
     shared_libs: [
         "android.hardware.audio.common-util",
-        "audioclient-types-aidl-cpp",
-        "audioflinger-aidl-cpp",
-        "audiopolicy-aidl-cpp",
-        "audiopolicy-types-aidl-cpp",
-        "av-types-aidl-cpp",
-        "capture_state_listener-aidl-cpp",
-        "effect-aidl-cpp",
-        "framework-permission-aidl-cpp",
-        "libactivitymanager_aidl",
-        "libaudioclient",
-        "libaudioclient_aidl_conversion",
         "libaudioflinger",
-        "libaudiofoundation",
-        "libaudiohal",
-        "libaudiomanager",
-        "libaudiopolicy",
-        "libaudiopolicymanagerdefault",
         "libaudiopolicyservice",
-        "libaudioprocessing",
-        "libaudioutils",
         "libdl",
-        "libheadtracking",
-        "libmediametrics",
-        "libmediautils",
-        "libnbaio",
-        "libnblog",
-        "libpowermanager",
-        "libvibrator",
         "libvndksupport",
-        "libxml2",
         "mediametricsservice-aidl-cpp",
-        "packagemanager_aidl-cpp",
     ],
     header_libs: [
-        "libaudioflinger_headers",
-        "libaudiofoundation_headers",
-        "libaudiohal_headers",
         "libaudiopolicymanager_interface_headers",
-        "libbinder_headers",
         "libmedia_headers",
     ],
     fuzz_config: {
@@ -99,6 +66,8 @@
         "latest_android_hardware_audio_core_sounddose_ndk_shared",
         "latest_android_hardware_audio_effect_ndk_shared",
         "libaudioclient_aidl_fuzzer_defaults",
+        "libaudioflinger_dependencies",
+        "libaudiopolicyservice_dependencies",
         "service_fuzzer_defaults",
     ],
 }
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-0 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..c1e1de5
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-1 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..8e49acd
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-2 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..a8ffcae
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-3 b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..7c25f6e
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index d4479ef..25d91d3 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -138,6 +138,12 @@
                                       audio_format_t format,
                                       audio_channel_mask_t channelMask);
 
+    /* Checks for erroneous status, marks error in MediaMetrics, logs the error message.
+     * Updates and returns mStatus.
+     */
+    status_t logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage,
+                                       const std::string& func);
+
     /* How data is transferred from AudioRecord
      */
     enum transfer_type {
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 3a001a4..de97863 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -233,8 +233,7 @@
      * FIXME This API assumes a route, and so should be deprecated.
      */
 
-    static status_t getMinFrameCount(size_t* frameCount,
-                                     audio_stream_type_t streamType,
+    static status_t getMinFrameCount(size_t* frameCount, audio_stream_type_t streamType,
                                      uint32_t sampleRate);
 
     /* Check if direct playback is possible for the given audio configuration and attributes.
@@ -243,6 +242,11 @@
     static bool isDirectOutputSupported(const audio_config_base_t& config,
                                         const audio_attributes_t& attributes);
 
+    /* Checks for erroneous status, logs the error message.
+     * Updates and returns mStatus.
+     */
+    status_t logIfErrorAndReturnStatus(status_t status, const std::string& errorMessage);
+
     /* How data is transferred to AudioTrack
      */
     enum transfer_type {
diff --git a/media/libaudioclient/include/media/PolicyAidlConversion.h b/media/libaudioclient/include/media/PolicyAidlConversion.h
index ed9ddd6..1b90d6b 100644
--- a/media/libaudioclient/include/media/PolicyAidlConversion.h
+++ b/media/libaudioclient/include/media/PolicyAidlConversion.h
@@ -28,8 +28,6 @@
 #include <android/media/AudioMixRouteFlag.h>
 #include <android/media/AudioMixType.h>
 #include <android/media/AudioOffloadMode.h>
-#include <android/media/AudioPolicyForceUse.h>
-#include <android/media/AudioPolicyForcedConfig.h>
 #include <android/media/DeviceRole.h>
 
 #include <media/AidlConversionUtil.h>
@@ -84,16 +82,6 @@
 ConversionResult<media::AudioPolicyDeviceState>
 legacy2aidl_audio_policy_dev_state_t_AudioPolicyDeviceState(audio_policy_dev_state_t legacy);
 
-ConversionResult<audio_policy_force_use_t>
-aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(media::AudioPolicyForceUse aidl);
-ConversionResult<media::AudioPolicyForceUse>
-legacy2aidl_audio_policy_force_use_t_AudioPolicyForceUse(audio_policy_force_use_t legacy);
-
-ConversionResult<audio_policy_forced_cfg_t>
-aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(media::AudioPolicyForcedConfig aidl);
-ConversionResult<media::AudioPolicyForcedConfig>
-legacy2aidl_audio_policy_forced_cfg_t_AudioPolicyForcedConfig(audio_policy_forced_cfg_t legacy);
-
 ConversionResult<device_role_t>
 aidl2legacy_DeviceRole_device_role_t(media::DeviceRole aidl);
 ConversionResult<media::DeviceRole>
diff --git a/media/libaudioclient/include/media/TrackPlayerBase.h b/media/libaudioclient/include/media/TrackPlayerBase.h
index fe88116..8df9ff8 100644
--- a/media/libaudioclient/include/media/TrackPlayerBase.h
+++ b/media/libaudioclient/include/media/TrackPlayerBase.h
@@ -19,6 +19,7 @@
 
 #include <media/AudioTrack.h>
 #include <media/PlayerBase.h>
+#include <mediautils/Synchronization.h>
 
 namespace android {
 
@@ -37,10 +38,11 @@
             const media::VolumeShaperConfiguration& configuration,
             const media::VolumeShaperOperation& operation);
 
-    //FIXME move to protected field, so far made public to minimize changes to AudioTrack logic
-    sp<AudioTrack> mAudioTrack;
+    sp<AudioTrack> getAudioTrack() { return mAudioTrack.load(); }
 
-            void setPlayerVolume(float vl, float vr);
+    void clearAudioTrack() { mAudioTrack.store(nullptr); }
+
+    void setPlayerVolume(float vl, float vr);
 
 protected:
 
@@ -68,6 +70,7 @@
     float mPlayerVolumeL, mPlayerVolumeR;
     sp<AudioTrack::IAudioTrackCallback> mCallbackHandle;
     sp<SelfAudioDeviceCallback> mSelfAudioDeviceCallback;
+    mediautils::atomic_sp<AudioTrack> mAudioTrack;
 };
 
 } // namespace android
diff --git a/media/libaudioclient/tests/audioeffect_tests.cpp b/media/libaudioclient/tests/audioeffect_tests.cpp
index 59d0c6a..bedeff9 100644
--- a/media/libaudioclient/tests/audioeffect_tests.cpp
+++ b/media/libaudioclient/tests/audioeffect_tests.cpp
@@ -70,8 +70,8 @@
     return effect;
 }
 
-status_t isEffectExistsOnAudioSession(const effect_uuid_t* type, const effect_uuid_t* uuid,
-                                      int priority, audio_session_t sessionId) {
+status_t createAndInitCheckEffect(const effect_uuid_t* type, const effect_uuid_t* uuid,
+                                  int priority, audio_session_t sessionId) {
     sp<AudioEffect> effect = createEffect(type, uuid, priority, sessionId);
     return effect->initCheck();
 }
@@ -272,10 +272,9 @@
     EXPECT_FALSE(isEffectDefaultOnRecord(selectedEffectType, selectedEffectUuid,
                                          capture->getAudioRecordHandle()))
             << "Effect should not have been default on record. " << type;
-    EXPECT_EQ(NO_ERROR,
-              isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
-                                           kDefaultInputEffectPriority - 1,
-                                           capture->getAudioRecordHandle()->getSessionId()))
+    EXPECT_EQ(NO_ERROR, createAndInitCheckEffect(selectedEffectType, selectedEffectUuid,
+                                                 kDefaultInputEffectPriority - 1,
+                                                 capture->getAudioRecordHandle()->getSessionId()))
             << "Effect should not have been added. " << type;
     EXPECT_EQ(OK, capture->audioProcess());
     EXPECT_EQ(OK, capture->stop());
@@ -296,9 +295,9 @@
                                         capture->getAudioRecordHandle()))
             << "Effect should have been default on record. " << type;
     EXPECT_EQ(ALREADY_EXISTS,
-              isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
-                                           kDefaultInputEffectPriority - 1,
-                                           capture->getAudioRecordHandle()->getSessionId()))
+              createAndInitCheckEffect(selectedEffectType, selectedEffectUuid,
+                                       kDefaultInputEffectPriority - 1,
+                                       capture->getAudioRecordHandle()->getSessionId()))
             << "Effect should have been added. " << type;
     EXPECT_EQ(OK, capture->audioProcess());
     EXPECT_EQ(OK, capture->stop());
@@ -313,10 +312,9 @@
     EXPECT_FALSE(isEffectDefaultOnRecord(selectedEffectType, selectedEffectUuid,
                                          capture->getAudioRecordHandle()))
             << "Effect should not have been default on record. " << type;
-    EXPECT_EQ(NO_ERROR,
-              isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
-                                           kDefaultInputEffectPriority - 1,
-                                           capture->getAudioRecordHandle()->getSessionId()))
+    EXPECT_EQ(NO_ERROR, createAndInitCheckEffect(selectedEffectType, selectedEffectUuid,
+                                                 kDefaultInputEffectPriority - 1,
+                                                 capture->getAudioRecordHandle()->getSessionId()))
             << "Effect should not have been added. " << type;
     EXPECT_EQ(OK, capture->audioProcess());
     EXPECT_EQ(OK, capture->stop());
@@ -421,8 +419,8 @@
     EXPECT_EQ(NO_ERROR, playback->create());
     EXPECT_EQ(NO_ERROR, playback->start());
     EXPECT_EQ(compatCheck ? NO_ERROR : NO_INIT,
-              isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
-                                           playback->getAudioTrackHandle()->getSessionId()))
+              createAndInitCheckEffect(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+                                       playback->getAudioTrackHandle()->getSessionId()))
             << "Effect should not have been added. " << mTypeStr;
     EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
     playback->stop();
@@ -445,8 +443,8 @@
     EXPECT_EQ(NO_ERROR, playback->start());
     // If effect chosen is not compatible with the session, then effect won't be applied
     EXPECT_EQ(compatCheck ? ALREADY_EXISTS : NO_INIT,
-              isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
-                                           playback->getAudioTrackHandle()->getSessionId()))
+              createAndInitCheckEffect(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+                                       playback->getAudioTrackHandle()->getSessionId()))
             << "Effect should have been added. " << mTypeStr;
     EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
     if (mSelectFastMode) {
@@ -467,8 +465,8 @@
     EXPECT_EQ(NO_ERROR, playback->create());
     EXPECT_EQ(NO_ERROR, playback->start());
     EXPECT_EQ(compatCheck ? NO_ERROR : NO_INIT,
-              isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
-                                           playback->getAudioTrackHandle()->getSessionId()))
+              createAndInitCheckEffect(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+                                       playback->getAudioTrackHandle()->getSessionId()))
             << "Effect should not have been added. " << mTypeStr;
     EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
     playback->stop();
@@ -502,8 +500,8 @@
     EXPECT_EQ(NO_ERROR, playback->create());
     EXPECT_EQ(NO_ERROR, playback->start());
 
-    EXPECT_EQ(ALREADY_EXISTS, isEffectExistsOnAudioSession(
-                                      &mType, &mUuid, kDefaultOutputEffectPriority - 1, sessionId))
+    EXPECT_EQ(ALREADY_EXISTS,
+              createAndInitCheckEffect(&mType, &mUuid, kDefaultOutputEffectPriority - 1, sessionId))
             << "Effect should have been added. " << mTypeStr;
     if (mSelectFastMode) {
         EXPECT_EQ(mIsFastCompatibleEffect ? AUDIO_OUTPUT_FLAG_FAST : 0,
@@ -556,8 +554,8 @@
     ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
     EXPECT_EQ(NO_ERROR, playback->create());
     EXPECT_EQ(NO_ERROR, playback->start());
-    EXPECT_TRUE(isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
-                                             kDefaultOutputEffectPriority - 1, sessionId))
+    ASSERT_EQ(ALREADY_EXISTS, createAndInitCheckEffect(selectedEffectType, selectedEffectUuid,
+                                                       kDefaultOutputEffectPriority - 1, sessionId))
             << "Effect should have been added. " << type;
     EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
     playback->stop();
diff --git a/media/libaudioclient/tests/trackplayerbase_tests.cpp b/media/libaudioclient/tests/trackplayerbase_tests.cpp
index 7317bf0..a4dba9b 100644
--- a/media/libaudioclient/tests/trackplayerbase_tests.cpp
+++ b/media/libaudioclient/tests/trackplayerbase_tests.cpp
@@ -54,7 +54,7 @@
         mPlayer = new TrackPlayer();
         mPlayer->init(track.get(), mPlayer, PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA,
                       AUDIO_SESSION_NONE);
-        sp<AudioTrack> playerTrack = mPlayer->mAudioTrack;
+        sp<AudioTrack> playerTrack = mPlayer->getAudioTrack();
         ASSERT_EQ(playerTrack->initCheck(), NO_ERROR);
 
         mBufferSize = mFrameCount * playerTrack->frameSize();
@@ -74,7 +74,7 @@
 
     void playBuffer() {
         bool blocking = true;
-        ssize_t nbytes = mPlayer->mAudioTrack->write(mBuffer.data(), mBufferSize, blocking);
+        ssize_t nbytes = mPlayer->getAudioTrack()->write(mBuffer.data(), mBufferSize, blocking);
         EXPECT_EQ(nbytes, mBufferSize) << "Did not write all data in blocking mode";
     }
 
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 639c7aa..75e2c11 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -45,6 +45,8 @@
         "liberror_headers",
         "libmediautils_headers",
     ],
+
+    export_include_dirs: ["include"],
 }
 
 cc_library_shared {
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
index 0fadd9c..fe00fb2 100644
--- a/media/libaudiohal/impl/ConversionHelperAidl.h
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -32,6 +32,28 @@
 
 namespace android {
 
+/*
+ * Helper macro to add instance name, function name in logs
+ * classes should provide getInstanceName API to use these macros.
+ * print function names along with instance name.
+ *
+ * Usage:
+ *  AUGMENT_LOG(D);
+ *  AUGMENT_LOG(I, "hello!");
+ *  AUGMENT_LOG(W, "value: %d", value);
+ *
+ *  AUGMENT_LOG_IF(D, value < 0, "negative");
+ *  AUGMENT_LOG_IF(E, value < 0, "bad value: %d", value);
+ */
+
+#define AUGMENT_LOG(level, ...)                                                  \
+    ALOG##level("[%s] %s" __VA_OPT__(": " __android_second(0, __VA_ARGS__, "")), \
+                getInstanceName().c_str(), __func__ __VA_OPT__(__android_rest(__VA_ARGS__)))
+
+#define AUGMENT_LOG_IF(level, cond, ...)                                                    \
+    ALOG##level##_IF(cond, "[%s] %s" __VA_OPT__(": " __android_second(0, __VA_ARGS__, "")), \
+                     getInstanceName().c_str(), __func__ __VA_OPT__(__android_rest(__VA_ARGS__)))
+
 class Args {
   public:
     explicit Args(const Vector<String16>& args)
@@ -49,13 +71,15 @@
 
 class ConversionHelperAidl {
   protected:
-    ConversionHelperAidl(std::string_view className) : mClassName(className) {}
+    ConversionHelperAidl(std::string_view className, std::string_view instanceName)
+        : mClassName(className), mInstanceName(instanceName) {}
 
-    const std::string& getClassName() const {
-        return mClassName;
-    }
+    const std::string& getClassName() const { return mClassName; }
+
+    const std::string& getInstanceName() const { return mInstanceName; }
 
     const std::string mClassName;
+    const std::string mInstanceName;
 };
 
 // 'action' must accept a value of type 'T' and return 'status_t'.
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
index 024589b..629cd7c 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -22,15 +22,20 @@
 #include <aidl/android/hardware/audio/core/BnStreamCallback.h>
 #include <aidl/android/hardware/audio/core/BnStreamOutEventCallback.h>
 #include <aidl/android/hardware/audio/core/StreamDescriptor.h>
+#include <android/binder_ibinder_platform.h>
 #include <error/expected_utils.h>
 #include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
 #include <media/AidlConversionNdkCpp.h>
 #include <media/AidlConversionUtil.h>
 #include <mediautils/TimeCheck.h>
 #include <system/audio.h>
+#include <system/thread_defs.h>
+
 #include <Utils.h>
 #include <utils/Log.h>
 
+#include "AidlUtils.h"
 #include "DeviceHalAidl.h"
 #include "EffectHalAidl.h"
 #include "StreamHalAidl.h"
@@ -60,6 +65,8 @@
 using aidl::android::hardware::audio::common::isBitPositionFlagSet;
 using aidl::android::hardware::audio::common::kDumpFromAudioServerArgument;
 using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using aidl::android::hardware::audio::common::SourceMetadata;
 using aidl::android::hardware::audio::core::sounddose::ISoundDose;
 using aidl::android::hardware::audio::core::AudioPatch;
 using aidl::android::hardware::audio::core::AudioRoute;
@@ -71,6 +78,18 @@
 using aidl::android::hardware::audio::core::ModuleDebug;
 using aidl::android::hardware::audio::core::VendorParameter;
 
+#define RETURN_IF_MODULE_NOT_INIT(retVal)         \
+    if (mModule == nullptr) {                     \
+        AUGMENT_LOG(E, "module not initialized"); \
+        return retVal;                            \
+    }
+
+#define RETURN_IF_TELEPHONY_NOT_INIT(retVal)         \
+    if (mTelephony == nullptr) {                     \
+        AUGMENT_LOG(E, "telephony not initialized"); \
+        return retVal;                               \
+    }
+
 namespace android {
 
 namespace {
@@ -103,15 +122,16 @@
 
 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)),
-          mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
-          mMapper(instance, module), mMapperAccessor(mMapper, mLock) {
-}
+    : ConversionHelperAidl("DeviceHalAidl", 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)),
+      mSoundDose(retrieveSubInterface<ISoundDose>(module, &IModule::getSoundDose)),
+      mMapper(instance, module),
+      mMapperAccessor(mMapper, mLock) {}
 
 status_t DeviceHalAidl::getAudioPorts(std::vector<media::audio::common::AudioPort> *ports) {
     std::lock_guard l(mLock);
@@ -124,11 +144,13 @@
 }
 
 status_t DeviceHalAidl::getSupportedModes(std::vector<media::audio::common::AudioMode> *modes) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
-    if (mTelephony == nullptr) return INVALID_OPERATION;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
+    RETURN_IF_TELEPHONY_NOT_INIT(INVALID_OPERATION);
+
     if (modes == nullptr) {
+        AUGMENT_LOG(E, "uninitialized modes");
         return BAD_VALUE;
     }
     std::vector<AudioMode> aidlModes;
@@ -146,48 +168,53 @@
 }
 
 status_t DeviceHalAidl::initCheck() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     std::lock_guard l(mLock);
     return mMapper.initialize();
 }
 
 status_t DeviceHalAidl::setVoiceVolume(float volume) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "volume %f", volume);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
-    if (mTelephony == nullptr) return INVALID_OPERATION;
-    ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
+    RETURN_IF_TELEPHONY_NOT_INIT(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);
+    AUGMENT_LOG_IF(
+            W, outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
+            "the resulting voice volume %f is not the same as requested %f",
+            outConfig.voiceVolume.value().value, volume);
     return OK;
 }
 
 status_t DeviceHalAidl::setMasterVolume(float volume) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "volume %f", volume);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     return statusTFromBinderStatus(mModule->setMasterVolume(volume));
 }
 
 status_t DeviceHalAidl::getMasterVolume(float *volume) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (volume == nullptr) {
+        AUGMENT_LOG(E, "uninitialized volumes");
         return BAD_VALUE;
     }
     return statusTFromBinderStatus(mModule->getMasterVolume(volume));
 }
 
 status_t DeviceHalAidl::setMode(audio_mode_t mode) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "mode %d", mode);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
     if (mTelephony != nullptr) {
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mTelephony->switchAudioMode(audioMode)));
@@ -196,90 +223,99 @@
 }
 
 status_t DeviceHalAidl::setMicMute(bool state) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "mute %d", state);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     return statusTFromBinderStatus(mModule->setMicMute(state));
 }
 
 status_t DeviceHalAidl::getMicMute(bool *state) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (state == nullptr) {
+        AUGMENT_LOG(E, "uninitialized mute state");
         return BAD_VALUE;
     }
     return statusTFromBinderStatus(mModule->getMicMute(state));
 }
 
 status_t DeviceHalAidl::setMasterMute(bool state) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "mute %d", state);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     return statusTFromBinderStatus(mModule->setMasterMute(state));
 }
 
 status_t DeviceHalAidl::getMasterMute(bool *state) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (state == nullptr) {
+        AUGMENT_LOG(E, "uninitialized mute state");
         return BAD_VALUE;
     }
     return statusTFromBinderStatus(mModule->getMasterMute(state));
 }
 
 status_t DeviceHalAidl::setParameters(const String8& kvPairs) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     AudioParameter parameters(kvPairs);
-    ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
+    AUGMENT_LOG(D, "parameters: \"%s\"", parameters.toString().c_str());
 
     if (status_t status = filterAndUpdateBtA2dpParameters(parameters); status != OK) {
-        ALOGW("%s: filtering or updating BT A2DP parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndUpdateBtA2dpParameters failed: %d", status);
     }
     if (status_t status = filterAndUpdateBtHfpParameters(parameters); status != OK) {
-        ALOGW("%s: filtering or updating BT HFP parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndUpdateBtHfpParameters failed: %d", status);
     }
     if (status_t status = filterAndUpdateBtLeParameters(parameters); status != OK) {
-        ALOGW("%s: filtering or updating BT LE parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndUpdateBtLeParameters failed: %d", status);
     }
     if (status_t status = filterAndUpdateBtScoParameters(parameters); status != OK) {
-        ALOGW("%s: filtering or updating BT SCO parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndUpdateBtScoParameters failed: %d", status);
     }
     if (status_t status = filterAndUpdateScreenParameters(parameters); status != OK) {
-        ALOGW("%s: filtering or updating screen parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndUpdateScreenParameters failed: %d", status);
     }
     if (status_t status = filterAndUpdateTelephonyParameters(parameters); status != OK) {
-        ALOGW("%s: filtering or updating telephony parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndUpdateTelephonyParameters failed: %d", status);
     }
     return parseAndSetVendorParameters(mVendorExt, mModule, parameters);
 }
 
 status_t DeviceHalAidl::getParameters(const String8& keys, String8 *values) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "keys: \"%s\"", keys.c_str());
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (values == nullptr) {
+        AUGMENT_LOG(E, "invalid values");
         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);
+        AUGMENT_LOG(W, "filterAndRetrieveBtA2dpParameters failed: %d", status);
     }
     if (status_t status = filterAndRetrieveBtLeParameters(parameterKeys, &result); status != OK) {
-        ALOGW("%s: filtering or retrieving BT LE parameters failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filterAndRetrieveBtLeParameters failed: %d", status);
     }
     *values = result.toString();
     return parseAndGetVendorParameters(mVendorExt, mModule, parameterKeys, values);
 }
 
 status_t DeviceHalAidl::getInputBufferSize(struct audio_config* config, size_t* size) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (config == nullptr || size == nullptr) {
+        AUGMENT_LOG(E, "invalid config or size");
         return BAD_VALUE;
     }
     constexpr bool isInput = true;
@@ -427,11 +463,14 @@
         audio_io_handle_t handle, audio_devices_t devices,
         audio_output_flags_t flags, struct audio_config* config,
         const char* address,
-        sp<StreamOutHalInterface>* outStream) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+        sp<StreamOutHalInterface>* outStream,
+        const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
+    AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (outStream == nullptr || config == nullptr) {
+        AUGMENT_LOG(E, "invalid outStream or config");
         return BAD_VALUE;
     }
     constexpr bool isInput = false;
@@ -443,9 +482,12 @@
             ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
     int32_t aidlOutputFlags = VALUE_OR_RETURN_STATUS(
             ::aidl::android::legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
+    SourceMetadata aidlMetadata = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_playback_track_metadata_v7_SourceMetadata(sourceMetadata));
     AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
     AudioPortConfig mixPortConfig;
     AudioPatch aidlPatch;
+
     Hal2AidlMapper::Cleanups cleanups(mMapperAccessor);
     {
         std::lock_guard l(mLock);
@@ -465,8 +507,15 @@
     std::shared_ptr<OutputStreamCallbackAidl> streamCb;
     if (isOffload) {
         streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
+        ndk::SpAIBinder binder = streamCb->asBinder();
+        AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+        AIBinder_setInheritRt(binder.get(), true);
     }
     auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
+    ndk::SpAIBinder binder = eventCb->asBinder();
+    AIBinder_setMinSchedulerPolicy(binder.get(), SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
+    AIBinder_setInheritRt(binder.get(), true);
+
     if (isOffload || isHwAvSync) {
         args.offloadInfo = aidlConfig.offloadInfo;
     }
@@ -475,12 +524,13 @@
     }
     args.bufferSizeFrames = aidlConfig.frameCount;
     args.eventCallback = eventCb;
+    args.sourceMetadata = aidlMetadata;
     ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
-    StreamContextAidl context(ret.desc, isOffload);
+    StreamContextAidl context(ret.desc, isOffload, aidlHandle);
     if (!context.isValid()) {
-        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
-                __func__, ret.desc.toString().c_str());
+        AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
+                    ret.desc.toString().c_str());
         return NO_INIT;
     }
     auto stream = sp<StreamOutHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
@@ -488,8 +538,11 @@
     *outStream = stream;
     /* StreamOutHalInterface* */ void* cbCookie = (*outStream).get();
     {
-        std::lock_guard l(mLock);
+        std::lock_guard l(mCallbacksLock);
         mCallbacks.emplace(cbCookie, Callbacks{});
+    }
+    {
+        std::lock_guard l(mLock);
         mMapper.addStream(*outStream, mixPortConfig.id, aidlPatch.id);
     }
     if (streamCb) {
@@ -509,10 +562,11 @@
         const char* address, audio_source_t source,
         audio_devices_t outputDevice, const char* outputDeviceAddress,
         sp<StreamInHalInterface>* inStream) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "handle: %d devices %0x flags %0x", handle, devices, flags);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (inStream == nullptr || config == nullptr) {
+        AUGMENT_LOG(E, "invalid inStream or config");
         return BAD_VALUE;
     }
     constexpr bool isInput = true;
@@ -552,10 +606,10 @@
     args.bufferSizeFrames = aidlConfig.frameCount;
     ::aidl::android::hardware::audio::core::IModule::OpenInputStreamReturn ret;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openInputStream(args, &ret)));
-    StreamContextAidl context(ret.desc, false /*isAsynchronous*/);
+    StreamContextAidl context(ret.desc, false /*isAsynchronous*/, aidlHandle);
     if (!context.isValid()) {
-        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
-                __func__, ret.desc.toString().c_str());
+        AUGMENT_LOG(E, "Failed to created a valid stream context from the descriptor: %s",
+                    ret.desc.toString().c_str());
         return NO_INIT;
     }
     *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), aidlPatch.latenciesMs[0],
@@ -569,7 +623,10 @@
 }
 
 status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
+    AUGMENT_LOG(V);
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (supportsPatches == nullptr) {
+        AUGMENT_LOG(E, "uninitialized supportsPatches");
         return BAD_VALUE;
     }
     *supportsPatches = true;
@@ -581,13 +638,20 @@
                                          unsigned int num_sinks,
                                          const struct audio_port_config* sinks,
                                          audio_patch_handle_t* patch) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "sources: %d sinks %d", num_sources, num_sinks);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
-    if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
-        sources == nullptr || sinks == nullptr || patch == nullptr) {
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
+    if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX) {
+        AUGMENT_LOG(E, "invalid sources %d or sinks %d ", num_sources, num_sinks);
         return BAD_VALUE;
     }
+
+    if (sources == nullptr || sinks == nullptr || patch == nullptr) {
+        AUGMENT_LOG(E, "uninitialized sources %d or sinks %d or patches %d", (sources == nullptr),
+                    (sinks == nullptr), (patch == nullptr));
+        return BAD_VALUE;
+    }
+
     // When the patch handle (*patch) is AUDIO_PATCH_HANDLE_NONE, it means
     // the framework wants to create a new patch. The handle has to be generated
     // by the HAL. Since handles generated this way can only be unique within
@@ -649,9 +713,10 @@
 }
 
 status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D, "patch: %d", patch);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
     if (patch == AUDIO_PATCH_HANDLE_NONE) {
         return BAD_VALUE;
@@ -674,7 +739,10 @@
 }
 
 status_t DeviceHalAidl::getAudioPort(struct audio_port* port) {
+    AUGMENT_LOG(V);
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (port == nullptr) {
+        AUGMENT_LOG(E, "port not initialized");
         return BAD_VALUE;
     }
     audio_port_v7 portV7;
@@ -684,10 +752,12 @@
 }
 
 status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (port == nullptr) {
+        AUGMENT_LOG(E, "port not initialized");
         return BAD_VALUE;
     }
     bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
@@ -695,8 +765,7 @@
     auto aidlPort = VALUE_OR_RETURN_STATUS(
             ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
     if (aidlPort.ext.getTag() != AudioPortExt::device) {
-        ALOGE("%s: provided port is not a device port (module %s): %s",
-                __func__, mInstance.c_str(), aidlPort.toString().c_str());
+        AUGMENT_LOG(E, "provided port is not a device port %s", aidlPort.toString().c_str());
         return BAD_VALUE;
     }
     const auto& matchDevice = aidlPort.ext.get<AudioPortExt::device>().device;
@@ -715,11 +784,13 @@
 
 status_t DeviceHalAidl::getAudioMixPort(const struct audio_port_v7 *devicePort,
                                         struct audio_port_v7 *mixPort) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
-    if (devicePort == nullptr || mixPort == nullptr ||
-            devicePort->type != AUDIO_PORT_TYPE_DEVICE || mixPort->type != AUDIO_PORT_TYPE_MIX) {
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
+
+    if (devicePort == nullptr || mixPort == nullptr || devicePort->type != AUDIO_PORT_TYPE_DEVICE ||
+        mixPort->type != AUDIO_PORT_TYPE_MIX) {
+        AUGMENT_LOG(E, "invalid device or mix port");
         return BAD_VALUE;
     }
     const int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
@@ -737,10 +808,12 @@
 }
 
 status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (config == nullptr) {
+        AUGMENT_LOG(E, "config not initialized");
         return BAD_VALUE;
     }
     bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
@@ -754,9 +827,10 @@
 }
 
 MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (!mModule) return {};
+    RETURN_IF_MODULE_NOT_INIT({});
     std::lock_guard l(mLock);
     if (mMicrophones.status == Microphones::Status::UNKNOWN) {
         TIME_CHECK();
@@ -768,7 +842,7 @@
         } else if (status == INVALID_OPERATION) {
             mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
         } else {
-            ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
+            AUGMENT_LOG(E, "Unexpected status from HAL: %d", status);
             return {};
         }
     }
@@ -780,10 +854,12 @@
 
 status_t DeviceHalAidl::getMicrophones(
         std::vector<audio_microphone_characteristic_t>* microphones) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (microphones == nullptr) {
+        AUGMENT_LOG(E, "microphones not initialized");
         return BAD_VALUE;
     }
     auto staticInfo = getMicrophoneInfo();
@@ -802,10 +878,12 @@
 
 status_t DeviceHalAidl::addDeviceEffect(
         const struct audio_port_config *device, sp<EffectHalInterface> effect) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (device == nullptr || effect == nullptr) {
+        AUGMENT_LOG(E, "device or effect not initialized");
         return BAD_VALUE;
     }
     bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
@@ -814,8 +892,8 @@
             ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                     *device, isInput, 0));
     if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
-        ALOGE("%s: provided port config is not a device port config: %s",
-                __func__, requestedPortConfig.toString().c_str());
+        AUGMENT_LOG(E, "provided port config is not a device port config: %s",
+                    requestedPortConfig.toString().c_str());
         return BAD_VALUE;
     }
     AudioPortConfig devicePortConfig;
@@ -833,10 +911,11 @@
 }
 status_t DeviceHalAidl::removeDeviceEffect(
         const struct audio_port_config *device, sp<EffectHalInterface> effect) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (device == nullptr || effect == nullptr) {
+        AUGMENT_LOG(E, "device or effect not initialized");
         return BAD_VALUE;
     }
     bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
@@ -845,8 +924,8 @@
             ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
                     *device, isInput, 0));
     if (requestedPortConfig.ext.getTag() != AudioPortExt::Tag::device) {
-        ALOGE("%s: provided port config is not a device port config: %s",
-                __func__, requestedPortConfig.toString().c_str());
+        AUGMENT_LOG(E, "provided port config is not a device port config: %s",
+                    requestedPortConfig.toString().c_str());
         return BAD_VALUE;
     }
     AudioPortConfig devicePortConfig;
@@ -864,11 +943,13 @@
 status_t DeviceHalAidl::getMmapPolicyInfos(
         media::audio::common::AudioMMapPolicyType policyType,
         std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
-    AudioMMapPolicyType mmapPolicyType = VALUE_OR_RETURN_STATUS(
-            cpp2ndk_AudioMMapPolicyType(policyType));
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
+
+    AudioMMapPolicyType mmapPolicyType =
+            VALUE_OR_RETURN_STATUS(cpp2ndk_AudioMMapPolicyType(policyType));
 
     std::vector<AudioMMapPolicyInfo> mmapPolicyInfos;
 
@@ -884,9 +965,10 @@
 }
 
 int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     int32_t mixerBurstCount = 0;
     if (mModule->getAAudioMixerBurstCount(&mixerBurstCount).isOk()) {
         return mixerBurstCount;
@@ -895,9 +977,10 @@
 }
 
 int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     int32_t hardwareBurstMinUsec = 0;
     if (mModule->getAAudioHardwareBurstMinUsec(&hardwareBurstMinUsec).isOk()) {
         return hardwareBurstMinUsec;
@@ -906,9 +989,10 @@
 }
 
 error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     int32_t aidlHwAvSync;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
     return VALUE_OR_RETURN_STATUS(
@@ -924,55 +1008,59 @@
 }
 
 status_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
+
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (supports == nullptr) {
         return BAD_VALUE;
     }
     return statusTFromBinderStatus(mModule->supportsVariableLatency(supports));
 }
 
-status_t DeviceHalAidl::getSoundDoseInterface(const std::string& module,
-                                              ::ndk::SpAIBinder* soundDoseBinder)  {
+status_t DeviceHalAidl::getSoundDoseInterface([[maybe_unused]] const std::string& module,
+                                              ::ndk::SpAIBinder* soundDoseBinder) {
+    AUGMENT_LOG(V);
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
+
     if (soundDoseBinder == nullptr) {
         return BAD_VALUE;
     }
     if (mSoundDose == nullptr) {
-        ALOGE("%s failed to retrieve the sound dose interface for module %s",
-                __func__, module.c_str());
+        AUGMENT_LOG(E, "failed to retrieve the sound dose interface");
         return BAD_VALUE;
     }
 
     if (mSoundDose == nullptr) {
-        ALOGE("%s failed to return the sound dose interface for module %s: not implemented",
-                  __func__,
-                  module.c_str());
+        AUGMENT_LOG(E, "failed to return the sound dose interface not implemented");
         return NO_INIT;
     }
 
     *soundDoseBinder = mSoundDose->asBinder();
-    ALOGI("%s using audio AIDL HAL sound dose interface", __func__);
+    AUGMENT_LOG(I, "using audio AIDL HAL sound dose interface");
     return OK;
 }
 
 status_t DeviceHalAidl::prepareToDisconnectExternalDevice(const struct audio_port_v7* port) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (port == nullptr) {
+        AUGMENT_LOG(E, "port not initialized");
         return BAD_VALUE;
     }
-    const bool isInput = VALUE_OR_RETURN_STATUS(
-            ::aidl::android::portDirection(port->role, port->type)) ==
-                    ::aidl::android::AudioPortDirection::INPUT;
+    const bool isInput =
+            VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(port->role, port->type)) ==
+            ::aidl::android::AudioPortDirection::INPUT;
     AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
             ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
     if (aidlPort.ext.getTag() != AudioPortExt::device) {
-        ALOGE("%s: provided port is not a device port (module %s): %s",
-              __func__, mInstance.c_str(), aidlPort.toString().c_str());
+        AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
         return BAD_VALUE;
     }
+
+    AUGMENT_LOG(D, "device %s", aidlPort.toString().c_str());
+
     status_t status = NO_ERROR;
     {
         std::lock_guard l(mLock);
@@ -993,10 +1081,11 @@
 }
 
 status_t DeviceHalAidl::setConnectedState(const struct audio_port_v7 *port, bool connected) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     if (port == nullptr) {
+        AUGMENT_LOG(E, "port not initialized");
         return BAD_VALUE;
     }
     if (!connected) {
@@ -1015,17 +1104,18 @@
     AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
             ::aidl::android::legacy2aidl_audio_port_v7_AudioPort(*port, isInput));
     if (aidlPort.ext.getTag() != AudioPortExt::device) {
-        ALOGE("%s: provided port is not a device port (module %s): %s",
-                __func__, mInstance.c_str(), aidlPort.toString().c_str());
+        AUGMENT_LOG(E, "provided port is not a device port: %s", aidlPort.toString().c_str());
         return BAD_VALUE;
     }
+    AUGMENT_LOG(D, "connected %d port: %s", connected, aidlPort.toString().c_str());
     std::lock_guard l(mLock);
     return mMapper.setDevicePortConnectedState(aidlPort, connected);
 }
 
 status_t DeviceHalAidl::setSimulateDeviceConnections(bool enabled) {
+    AUGMENT_LOG(V);
     TIME_CHECK();
-    if (mModule == nullptr) return NO_INIT;
+    RETURN_IF_MODULE_NOT_INIT(NO_INIT);
     {
         std::lock_guard l(mLock);
         mMapper.resetUnusedPatchesAndPortConfigs();
@@ -1034,9 +1124,9 @@
     status_t status = statusTFromBinderStatus(mModule->setModuleDebug(debug));
     // This is important to log as it affects HAL behavior.
     if (status == OK) {
-        ALOGI("%s: set enabled: %d", __func__, enabled);
+        AUGMENT_LOG(I, "set enabled: %d", enabled);
     } else {
-        ALOGW("%s: set enabled to %d failed: %d", __func__, enabled, status);
+        AUGMENT_LOG(W, "set enabled to %d failed: %d", enabled, status);
     }
     return status;
 }
@@ -1051,7 +1141,7 @@
                             mBluetoothA2dp->supportsOffloadReconfiguration(&supports)));
             result->addInt(key, supports ? 1 : 0);
         } else {
-            ALOGI("%s: no IBluetoothA2dp on %s", __func__, mInstance.c_str());
+            AUGMENT_LOG(I, "no IBluetoothA2dp");
             result->addInt(key, 0);
         }
     }
@@ -1068,7 +1158,7 @@
                             mBluetoothLe->supportsOffloadReconfiguration(&supports)));
             result->addInt(key, supports ? 1 : 0);
         } else {
-            ALOGI("%s: no mBluetoothLe on %s", __func__, mInstance.c_str());
+            AUGMENT_LOG(I, "no mBluetoothLe");
             result->addInt(key, 0);
         }
     }
@@ -1079,29 +1169,29 @@
     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;
-                    }));
+            parameters, String8(AudioParameter::keyBtA2dpSuspended),
+            [&a2dpEnabled, this](const String8& trueOrFalse) {
+                if (trueOrFalse == AudioParameter::valueTrue) {
+                    a2dpEnabled = false;  // 'suspended' == true
+                    return OK;
+                } else if (trueOrFalse == AudioParameter::valueFalse) {
+                    a2dpEnabled = true;  // 'suspended' == false
+                    return OK;
+                }
+                AUGMENT_LOG(E, "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 {
-                        std::vector<VendorParameter> result;
-                        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
-                                mVendorExt->parseBluetoothA2dpReconfigureOffload(
-                                        std::string(value.c_str()), &result)));
-                        reconfigureOffload = std::move(result);
-                        return OK;
-                    }));
+            parameters, String8(AudioParameter::keyReconfigA2dp),
+            [&](const String8& value) -> status_t {
+                std::vector<VendorParameter> result;
+                RETURN_STATUS_IF_ERROR(
+                        statusTFromBinderStatus(mVendorExt->parseBluetoothA2dpReconfigureOffload(
+                                std::string(value.c_str()), &result)));
+                reconfigureOffload = std::move(result);
+                return OK;
+            }));
     if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
         return statusTFromBinderStatus(mBluetoothA2dp->setEnabled(a2dpEnabled.value()));
     }
@@ -1115,34 +1205,33 @@
 status_t DeviceHalAidl::filterAndUpdateBtHfpParameters(AudioParameter &parameters) {
     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;
-                    }));
+            parameters, String8(AudioParameter::keyBtHfpEnable),
+            [&hfpConfig, this](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;
+                }
+                AUGMENT_LOG(E, "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;
-                    }));
+            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;
-                    }));
+            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));
@@ -1154,39 +1243,39 @@
     std::optional<bool> leEnabled;
     std::optional<std::vector<VendorParameter>> reconfigureOffload;
     (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;
-                    }));
+            parameters, String8(AudioParameter::keyBtLeSuspended),
+            [&leEnabled, this](const String8& trueOrFalse) {
+                if (trueOrFalse == AudioParameter::valueTrue) {
+                    leEnabled = false;  // 'suspended' == true
+                    return OK;
+                } else if (trueOrFalse == AudioParameter::valueFalse) {
+                    leEnabled = true;  // 'suspended' == false
+                    return OK;
+                }
+                AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                            AudioParameter::keyBtLeSuspended, trueOrFalse.c_str());
+                return BAD_VALUE;
+            }));
     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
-                    parameters, String8(AudioParameter::keyReconfigLe),
-                    [&](const String8& value) -> status_t {
-                        if (mVendorExt != nullptr) {
-                            std::vector<VendorParameter> result;
-                            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
-                                    mVendorExt->parseBluetoothLeReconfigureOffload(
-                                            std::string(value.c_str()), &result)));
-                            reconfigureOffload = std::move(result);
-                        } else {
-                            reconfigureOffload = std::vector<VendorParameter>();
-                        }
-                        return OK;
-                    }));
+            parameters, String8(AudioParameter::keyReconfigLe),
+            [&](const String8& value) -> status_t {
+                if (mVendorExt != nullptr) {
+                    std::vector<VendorParameter> result;
+                    RETURN_STATUS_IF_ERROR(
+                            statusTFromBinderStatus(mVendorExt->parseBluetoothLeReconfigureOffload(
+                                    std::string(value.c_str()), &result)));
+                    reconfigureOffload = std::move(result);
+                } else {
+                    reconfigureOffload = std::vector<VendorParameter>();
+                }
+                return OK;
+            }));
     if (mBluetoothLe != nullptr && leEnabled.has_value()) {
         return statusTFromBinderStatus(mBluetoothLe->setEnabled(leEnabled.value()));
     }
     if (mBluetoothLe != nullptr && reconfigureOffload.has_value()) {
-        return statusTFromBinderStatus(mBluetoothLe->reconfigureOffload(
-                        reconfigureOffload.value()));
+        return statusTFromBinderStatus(
+                mBluetoothLe->reconfigureOffload(reconfigureOffload.value()));
     }
     return OK;
 }
@@ -1194,53 +1283,53 @@
 status_t DeviceHalAidl::filterAndUpdateBtScoParameters(AudioParameter &parameters) {
     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;
-                    }));
+            parameters, String8(AudioParameter::keyBtSco),
+            [&scoConfig, this](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;
+                }
+                AUGMENT_LOG(E, "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;
-                    }));
+            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;
-                    }));
+            parameters, String8(AudioParameter::keyBtNrec),
+            [&scoConfig, this](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;
+                }
+                AUGMENT_LOG(E, "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;
-                    }));
+            parameters, String8(AudioParameter::keyBtScoWb),
+            [&scoConfig, this](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;
+                }
+                AUGMENT_LOG(E, "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));
@@ -1250,34 +1339,41 @@
 
 status_t DeviceHalAidl::filterAndUpdateScreenParameters(AudioParameter &parameters) {
     (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()));
-                    }));
+            parameters, String8(AudioParameter::keyScreenState),
+            [&, this](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()) {
+                    AUGMENT_LOG(E, "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 {
+            parameters, String8(AudioParameter::keyScreenRotation),
+            [&, this](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;
+                    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);
+                        AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value %d",
+                                    AudioParameter::keyScreenRotation, rotationDegrees);
                         return BAD_VALUE;
                 }
                 return statusTFromBinderStatus(mModule->updateScreenRotation(rotation));
@@ -1289,49 +1385,48 @@
     using TtyMode = ITelephony::TelecomConfig::TtyMode;
     ITelephony::TelecomConfig telConfig;
     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
-                    parameters, String8(AudioParameter::keyTtyMode),
-                    [&telConfig](const String8& mode) {
-                        if (mode == AudioParameter::valueTtyModeOff) {
-                            telConfig.ttyMode = TtyMode::OFF;
-                            return OK;
-                        } else if (mode == AudioParameter::valueTtyModeFull) {
-                            telConfig.ttyMode = TtyMode::FULL;
-                            return OK;
-                        } else if (mode == AudioParameter::valueTtyModeHco) {
-                            telConfig.ttyMode = TtyMode::HCO;
-                            return OK;
-                        } else if (mode == AudioParameter::valueTtyModeVco) {
-                            telConfig.ttyMode = TtyMode::VCO;
-                            return OK;
-                        }
-                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
-                                AudioParameter::keyTtyMode, mode.c_str());
-                        return BAD_VALUE;
-                    }));
+            parameters, String8(AudioParameter::keyTtyMode),
+            [&telConfig, this](const String8& mode) {
+                if (mode == AudioParameter::valueTtyModeOff) {
+                    telConfig.ttyMode = TtyMode::OFF;
+                    return OK;
+                } else if (mode == AudioParameter::valueTtyModeFull) {
+                    telConfig.ttyMode = TtyMode::FULL;
+                    return OK;
+                } else if (mode == AudioParameter::valueTtyModeHco) {
+                    telConfig.ttyMode = TtyMode::HCO;
+                    return OK;
+                } else if (mode == AudioParameter::valueTtyModeVco) {
+                    telConfig.ttyMode = TtyMode::VCO;
+                    return OK;
+                }
+                AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                            AudioParameter::keyTtyMode, mode.c_str());
+                return BAD_VALUE;
+            }));
     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
-                    parameters, String8(AudioParameter::keyHacSetting),
-                    [&telConfig](const String8& onOrOff) {
-                        if (onOrOff == AudioParameter::valueHacOn) {
-                            telConfig.isHacEnabled = Boolean{ .value = true };
-                            return OK;
-                        } else if (onOrOff == AudioParameter::valueHacOff) {
-                            telConfig.isHacEnabled = Boolean{ .value = false };
-                            return OK;
-                        }
-                        ALOGE("setParameters: parameter key \"%s\" has invalid value \"%s\"",
-                                AudioParameter::keyHacSetting, onOrOff.c_str());
-                        return BAD_VALUE;
-                    }));
+            parameters, String8(AudioParameter::keyHacSetting),
+            [&telConfig, this](const String8& onOrOff) {
+                if (onOrOff == AudioParameter::valueHacOn) {
+                    telConfig.isHacEnabled = Boolean{.value = true};
+                    return OK;
+                } else if (onOrOff == AudioParameter::valueHacOff) {
+                    telConfig.isHacEnabled = Boolean{.value = false};
+                    return OK;
+                }
+                AUGMENT_LOG(E, "setParameters: parameter key \"%s\" has invalid value \"%s\"",
+                            AudioParameter::keyHacSetting, onOrOff.c_str());
+                return BAD_VALUE;
+            }));
     if (mTelephony != nullptr && telConfig != ITelephony::TelecomConfig{}) {
         ITelephony::TelecomConfig newTelConfig;
-        return statusTFromBinderStatus(
-                mTelephony->setTelecomConfig(telConfig, &newTelConfig));
+        return statusTFromBinderStatus(mTelephony->setTelecomConfig(telConfig, &newTelConfig));
     }
     return OK;
 }
 
 void DeviceHalAidl::clearCallbacks(void* cookie) {
-    std::lock_guard l(mLock);
+    std::lock_guard l(mCallbacksLock);
     mCallbacks.erase(cookie);
 }
 
@@ -1364,18 +1459,21 @@
     setCallbackImpl(cookie, &Callbacks::latency, cb);
 }
 
-template<class C>
+template <class C>
 sp<C> DeviceHalAidl::getCallbackImpl(void* cookie, wp<C> DeviceHalAidl::Callbacks::* field) {
-    std::lock_guard l(mLock);
-    if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
-        return ((it->second).*field).promote();
+    wp<C> result;
+    {
+        std::lock_guard l(mCallbacksLock);
+        if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+            result = (it->second).*field;
+        }
     }
-    return nullptr;
+    return result.promote();
 }
 template<class C>
 void DeviceHalAidl::setCallbackImpl(
         void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
-    std::lock_guard l(mLock);
+    std::lock_guard l(mCallbacksLock);
     if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
         (it->second).*field = cb;
     }
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
index bcd495d..6ae6402 100644
--- a/media/libaudiohal/impl/DeviceHalAidl.h
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -119,7 +119,9 @@
     // by releasing all references to the returned object.
     status_t openOutputStream(audio_io_handle_t handle, audio_devices_t devices,
                               audio_output_flags_t flags, struct audio_config* config,
-                              const char* address, sp<StreamOutHalInterface>* outStream) override;
+                              const char* address, sp<StreamOutHalInterface>* outStream,
+                              const std::vector<playback_track_metadata_v7_t>&
+                                                               sourceMetadata = {}) override;
 
     // Creates and opens the audio hardware input stream. The stream is closed
     // by releasing all references to the returned object.
@@ -233,7 +235,6 @@
     // MicrophoneInfoProvider implementation
     MicrophoneInfoProvider::Info const* getMicrophoneInfo() override;
 
-    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;
@@ -242,8 +243,11 @@
     const std::shared_ptr<::aidl::android::hardware::audio::core::IBluetoothLe> mBluetoothLe;
     const std::shared_ptr<::aidl::android::hardware::audio::core::sounddose::ISoundDose> mSoundDose;
 
+    std::mutex mCallbacksLock;
+    // Use 'mCallbacksLock' only to implement exclusive access to 'mCallbacks'. Never hold it
+    // while making any calls.
+    std::map<void*, Callbacks> mCallbacks GUARDED_BY(mCallbacksLock);
     std::mutex mLock;
-    std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
     std::set<audio_port_handle_t> mDeviceDisconnectionNotified GUARDED_BY(mLock);
     Hal2AidlMapper mMapper GUARDED_BY(mLock);
     LockedAccessor<Hal2AidlMapper> mMapperAccessor;
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index ea4258c..0a262e4 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -259,7 +259,8 @@
         audio_output_flags_t flags,
         struct audio_config *config,
         const char *address,
-        sp<StreamOutHalInterface> *outStream) {
+        sp<StreamOutHalInterface> *outStream,
+        const std::vector<playback_track_metadata_v7_t>& sourceMetadata) {
     TIME_CHECK();
     if (mDevice == 0) return NO_INIT;
     DeviceAddress hidlDevice;
@@ -273,6 +274,16 @@
         return status;
     }
 
+#if MAJOR_VERSION == 4
+    ::android::hardware::audio::CORE_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
+#else
+    ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION::SourceMetadata hidlMetadata;
+#endif
+
+    RETURN_STATUS_IF_ERROR(CoreUtils::sourceMetadataFromHalV7(
+            sourceMetadata, true /*ignoreNonVendorTags*/, &hidlMetadata
+            ));
+
 #if !(MAJOR_VERSION == 7 && MINOR_VERSION == 1)
     //TODO: b/193496180 use spatializer flag at audio HAL when available
     if ((flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) {
@@ -294,7 +305,7 @@
 #endif
             handle, hidlDevice, hidlConfig, hidlFlags,
 #if MAJOR_VERSION >= 4
-            {} /* metadata */,
+            hidlMetadata /* metadata */,
 #endif
             [&](Result r, const sp<::android::hardware::audio::CPP_VERSION::IStreamOut>& result,
                     const AudioConfig& suggestedConfig) {
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index 1362dab..5f3e08c 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -73,7 +73,9 @@
     // by releasing all references to the returned object.
     status_t openOutputStream(audio_io_handle_t handle, audio_devices_t devices,
                               audio_output_flags_t flags, struct audio_config* config,
-                              const char* address, sp<StreamOutHalInterface>* outStream) override;
+                              const char* address, sp<StreamOutHalInterface>* outStream,
+                              const std::vector<playback_track_metadata_v7_t>&
+                                                                sourceMetadata = {}) override;
 
     // Creates and opens the audio hardware input stream. The stream is closed
     // by releasing all references to the returned object.
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index a13903b..f719d97 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -532,5 +532,13 @@
                            AudioChannelLayout::LAYOUT_HAPTIC_AB /* mask */);
 }
 
+size_t EffectConversionHelperAidl::getInputChannelCount() const {
+    return getChannelCount(mCommon.input.base.channelMask);
+}
+
+size_t EffectConversionHelperAidl::getOutputChannelCount() const {
+    return getChannelCount(mCommon.output.base.channelMask);
+}
+
 }  // namespace effect
 }  // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 50b47a9..e9e9fc2 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -51,6 +51,8 @@
 
     size_t getAudioChannelCount() const;
     size_t getHapticChannelCount() const;
+    size_t getInputChannelCount() const;
+    size_t getOutputChannelCount() const;
 
     uint8_t mOutputAccessMode = EFFECT_BUFFER_ACCESS_WRITE;
 
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index ea4dbf6..9fdde49 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -75,7 +75,14 @@
       mEffect(effect),
       mSessionId(sessionId),
       mIoId(ioId),
-      mIsProxyEffect(isProxyEffect) {
+      mIsProxyEffect(isProxyEffect),
+      mHalVersion([factory]() {
+          int version = 0;
+          // use factory HAL version because effect can be an EffectProxy instance
+          return factory->getInterfaceVersion(&version).isOk() ? version : 0;
+      }()),
+      mEventFlagDataMqNotEmpty(mHalVersion >= kReopenSupportedVersion ? kEventFlagDataMqNotEmpty
+                                                                      : kEventFlagNotEmpty) {
     assert(mFactory != nullptr);
     assert(mEffect != nullptr);
     createAidlConversion(effect, sessionId, ioId, desc);
@@ -159,6 +166,7 @@
         mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
                 effect, sessionId, ioId, desc, mIsProxyEffect);
     }
+    mEffectName = mConversion->getDescriptor().common.name;
     return OK;
 }
 
@@ -174,100 +182,153 @@
 
 // write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
 status_t EffectHalAidl::process() {
-    const std::string effectName = mConversion->getDescriptor().common.name;
     State state = State::INIT;
     if (mConversion->isBypassing() || !mEffect->getState(&state).isOk() ||
         state != State::PROCESSING) {
-        ALOGI("%s skipping %s process because it's %s", __func__, effectName.c_str(),
+        ALOGI("%s skipping process because it's %s", mEffectName.c_str(),
               mConversion->isBypassing()
                       ? "bypassing"
                       : aidl::android::hardware::audio::effect::toString(state).c_str());
         return -ENODATA;
     }
 
-    // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
-    auto efGroup = mConversion->getEventFlagGroup();
+    const std::shared_ptr<android::hardware::EventFlag> efGroup = mConversion->getEventFlagGroup();
     if (!efGroup) {
-        ALOGE("%s invalid efGroup", __func__);
+        ALOGE("%s invalid efGroup", mEffectName.c_str());
         return INVALID_OPERATION;
     }
 
-    // use IFactory HAL version because IEffect can be an EffectProxy instance
-    static const int halVersion = [&]() {
-        int version = 0;
-        return mFactory->getInterfaceVersion(&version).isOk() ? version : 0;
-    }();
+    // reopen if halVersion >= kReopenSupportedVersion and receive kEventFlagDataMqUpdate
+    RETURN_STATUS_IF_ERROR(maybeReopen(efGroup));
+    const size_t samplesWritten = writeToHalInputFmqAndSignal(efGroup);
+    if (0 == samplesWritten) {
+        return INVALID_OPERATION;
+    }
 
-    if (uint32_t efState = 0; halVersion >= kReopenSupportedVersion &&
-                              ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
+    RETURN_STATUS_IF_ERROR(waitHalStatusFmq(samplesWritten));
+    RETURN_STATUS_IF_ERROR(readFromHalOutputFmq(samplesWritten));
+    return OK;
+}
+
+status_t EffectHalAidl::maybeReopen(
+        const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
+    if (mHalVersion < kReopenSupportedVersion) {
+        return OK;
+    }
+
+    // check if the DataMq needs any update, timeout at 1ns to avoid being blocked
+    if (uint32_t efState = 0; ::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
                                                              1 /* ns */, true /* retry */) &&
                               efState & kEventFlagDataMqUpdate) {
-        ALOGD("%s %s V%d receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str(),
-              halVersion);
-
-        mConversion->reopen();
+        ALOGD("%s V%d receive dataMQUpdate eventFlag from HAL", mEffectName.c_str(), mHalVersion);
+        return mConversion->reopen();
     }
-    auto statusQ = mConversion->getStatusMQ();
-    auto inputQ = mConversion->getInputMQ();
-    auto outputQ = mConversion->getOutputMQ();
-    if (!statusQ || !statusQ->isValid() || !inputQ || !inputQ->isValid() || !outputQ ||
-        !outputQ->isValid()) {
-        ALOGE("%s invalid FMQ [Status %d I %d O %d]", __func__, statusQ ? statusQ->isValid() : 0,
-              inputQ ? inputQ->isValid() : 0, outputQ ? outputQ->isValid() : 0);
-        return INVALID_OPERATION;
+    return OK;
+}
+
+size_t EffectHalAidl::writeToHalInputFmqAndSignal(
+        const std::shared_ptr<android::hardware::EventFlag>& efGroup) const {
+    const auto inputQ = mConversion->getInputMQ();
+    if (!inputQ || !inputQ->isValid()) {
+        ALOGE("%s invalid input FMQ", mEffectName.c_str());
+        return 0;
     }
 
-    size_t available = inputQ->availableToWrite();
-    const size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
-    if (floatsToWrite == 0) {
-        ALOGE("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
-              mInBuffer->getSize() / sizeof(float), available);
-        return INVALID_OPERATION;
-    }
-    if (!mInBuffer->audioBuffer() ||
-        !inputQ->write((float*)mInBuffer->audioBuffer()->f32, floatsToWrite)) {
-        ALOGE("%s failed to write %zu floats from audiobuffer %p to inputQ [avail %zu]", __func__,
-              floatsToWrite, mInBuffer->audioBuffer(), inputQ->availableToWrite());
-        return INVALID_OPERATION;
+    const size_t fmqSpaceSamples = inputQ->availableToWrite();
+    const size_t samplesInBuffer =
+            mInBuffer->audioBuffer()->frameCount * mConversion->getInputChannelCount();
+    const size_t samplesToWrite = std::min(fmqSpaceSamples, samplesInBuffer);
+    if (samplesToWrite == 0) {
+        ALOGE("%s not able to write, samplesInBuffer %zu, fmqSpaceSamples %zu", mEffectName.c_str(),
+              samplesInBuffer, fmqSpaceSamples);
+        return 0;
     }
 
-    // for V2 audio effect HAL, expect different EventFlag to avoid bit conflict with FMQ_NOT_EMPTY
-    efGroup->wake(halVersion >= kReopenSupportedVersion ? kEventFlagDataMqNotEmpty
-                                                        : kEventFlagNotEmpty);
+    const float* const inputRawBuffer = static_cast<const float*>(mInBuffer->audioBuffer()->f32);
+    if (!inputQ->write(inputRawBuffer, samplesToWrite)) {
+        ALOGE("%s failed to write %zu samples to inputQ [avail %zu]", mEffectName.c_str(),
+              samplesToWrite, inputQ->availableToWrite());
+        return 0;
+    }
+
+    efGroup->wake(mEventFlagDataMqNotEmpty);
+    return samplesToWrite;
+}
+
+void EffectHalAidl::writeHapticGeneratorData(size_t totalSamples, float* const outputRawBuffer,
+                                             float* const fmqOutputBuffer) const {
+    const auto audioChNum = mConversion->getAudioChannelCount();
+    const auto audioSamples =
+            totalSamples * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
+
+    static constexpr float kHalFloatSampleLimit = 2.0f;
+    // for HapticGenerator, the input data buffer will be updated
+    float* const inputRawBuffer = static_cast<float*>(mInBuffer->audioBuffer()->f32);
+    // accumulate or copy input to output, haptic samples remains all zero
+    if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+        accumulate_float(outputRawBuffer, inputRawBuffer, audioSamples);
+    } else {
+        memcpy_to_float_from_float_with_clamping(outputRawBuffer, inputRawBuffer, audioSamples,
+                                                 kHalFloatSampleLimit);
+    }
+    // append the haptic sample at the end of input audio samples
+    memcpy_to_float_from_float_with_clamping(inputRawBuffer + audioSamples,
+                                             fmqOutputBuffer + audioSamples,
+                                             totalSamples - audioSamples, kHalFloatSampleLimit);
+}
+
+status_t EffectHalAidl::waitHalStatusFmq(size_t samplesWritten) const {
+    const auto statusQ = mConversion->getStatusMQ();
+    if (const bool statusValid = statusQ && statusQ->isValid(); !statusValid) {
+        ALOGE("%s statusFMQ %s", mEffectName.c_str(), statusValid ? "valid" : "invalid");
+        return INVALID_OPERATION;
+    }
 
     IEffect::Status retStatus{};
     if (!statusQ->readBlocking(&retStatus, 1)) {
-        ALOGE("%s %s V%d read status from status FMQ failed", __func__, effectName.c_str(),
-              halVersion);
+        ALOGE("%s V%d read status from status FMQ failed", mEffectName.c_str(), mHalVersion);
         return INVALID_OPERATION;
     }
-    if (retStatus.status != OK || (size_t)retStatus.fmqConsumed != floatsToWrite ||
+    if (retStatus.status != OK || (size_t)retStatus.fmqConsumed != samplesWritten ||
         retStatus.fmqProduced == 0) {
-        ALOGE("%s read status failed: %s, consumed %d (of %zu) produced %d", __func__,
-              retStatus.toString().c_str(), retStatus.fmqConsumed, floatsToWrite,
-              retStatus.fmqProduced);
+        ALOGE("%s read status failed: %s, FMQ consumed %d (of %zu) produced %d",
+              mEffectName.c_str(), retStatus.toString().c_str(), retStatus.fmqConsumed,
+              samplesWritten, retStatus.fmqProduced);
         return INVALID_OPERATION;
     }
 
-    available = outputQ->availableToRead();
-    const size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
-    if (floatsToRead == 0) {
-        ALOGE("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
-              mOutBuffer->getSize() / sizeof(float), available);
+    return OK;
+}
+
+status_t EffectHalAidl::readFromHalOutputFmq(size_t samplesWritten) const {
+    const auto outputQ = mConversion->getOutputMQ();
+    if (const bool outputValid = outputQ && outputQ->isValid(); !outputValid) {
+        ALOGE("%s outputFMQ %s", mEffectName.c_str(), outputValid ? "valid" : "invalid");
         return INVALID_OPERATION;
     }
 
-    float *outputRawBuffer = mOutBuffer->audioBuffer()->f32;
+    const size_t fmqProducedSamples = outputQ->availableToRead();
+    const size_t bufferSpaceSamples =
+            mOutBuffer->audioBuffer()->frameCount * mConversion->getOutputChannelCount();
+    const size_t samplesToRead = std::min(fmqProducedSamples, bufferSpaceSamples);
+    if (samplesToRead == 0) {
+        ALOGE("%s unable to read, bufferSpace %zu, fmqProduced %zu samplesWritten %zu",
+              mEffectName.c_str(), bufferSpaceSamples, fmqProducedSamples, samplesWritten);
+        return INVALID_OPERATION;
+    }
+
+    float* const outputRawBuffer = static_cast<float*>(mOutBuffer->audioBuffer()->f32);
+    float* fmqOutputBuffer = outputRawBuffer;
     std::vector<float> tempBuffer;
     // keep original data in the output buffer for accumulate mode or HapticGenerator effect
     if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE || mIsHapticGenerator) {
-        tempBuffer.resize(floatsToRead);
-        outputRawBuffer = tempBuffer.data();
+        tempBuffer.resize(samplesToRead, 0);
+        fmqOutputBuffer = tempBuffer.data();
     }
     // always read floating point data for AIDL
-    if (!outputQ->read(outputRawBuffer, floatsToRead)) {
-        ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", __func__, floatsToRead,
-              mOutBuffer->audioBuffer());
+    if (!outputQ->read(fmqOutputBuffer, samplesToRead)) {
+        ALOGE("%s failed to read %zu from outputQ to audioBuffer %p", mEffectName.c_str(),
+              samplesToRead, fmqOutputBuffer);
         return INVALID_OPERATION;
     }
 
@@ -276,26 +337,10 @@
     // offset as input buffer, here we skip the audio samples in output FMQ and append haptic
     // samples to the end of input buffer
     if (mIsHapticGenerator) {
-        static constexpr float kHalFloatSampleLimit = 2.0f;
-        assert(floatsToRead == floatsToWrite);
-        const auto audioChNum = mConversion->getAudioChannelCount();
-        const auto audioSamples =
-                floatsToWrite * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
-        // accumulate or copy input to output, haptic samples remains all zero
-        if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
-            accumulate_float(mOutBuffer->audioBuffer()->f32, mInBuffer->audioBuffer()->f32,
-                             audioSamples);
-        } else {
-            memcpy_to_float_from_float_with_clamping(mOutBuffer->audioBuffer()->f32,
-                                                     mInBuffer->audioBuffer()->f32, audioSamples,
-                                                     kHalFloatSampleLimit);
-        }
-        // append the haptic sample at the end of input audio samples
-        memcpy_to_float_from_float_with_clamping(mInBuffer->audioBuffer()->f32 + audioSamples,
-                                                 outputRawBuffer + audioSamples,
-                                                 floatsToRead - audioSamples, kHalFloatSampleLimit);
+        assert(samplesRead == samplesWritten);
+        writeHapticGeneratorData(samplesToRead, outputRawBuffer, fmqOutputBuffer);
     } else if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
-        accumulate_float(mOutBuffer->audioBuffer()->f32, outputRawBuffer, floatsToRead);
+        accumulate_float(outputRawBuffer, fmqOutputBuffer, samplesToRead);
     }
 
     return OK;
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index 4f7de7c..a775337 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -73,7 +73,12 @@
     const int32_t mSessionId;
     const int32_t mIoId;
     const bool mIsProxyEffect;
+    const int32_t mHalVersion;
+    // Audio effect HAL v2+ changes flag to kEventFlagDataMqNotEmpty to avoid conflict from using
+    // kEventFlagNotEmpty
+    const uint32_t mEventFlagDataMqNotEmpty;
     bool mIsHapticGenerator = false;
+    std::string mEffectName;
 
     std::unique_ptr<EffectConversionHelperAidl> mConversion;
 
@@ -93,6 +98,14 @@
     bool setEffectReverse(bool reverse);
     bool needUpdateReturnParam(uint32_t cmdCode);
 
+    status_t maybeReopen(const std::shared_ptr<android::hardware::EventFlag>& efGroup) const;
+    void writeHapticGeneratorData(size_t totalSamples, float* const outputRawBuffer,
+                                  float* const fmqOutputBuffer) const;
+    size_t writeToHalInputFmqAndSignal(
+            const std::shared_ptr<android::hardware::EventFlag>& efGroup) const;
+    status_t waitHalStatusFmq(size_t samplesWritten) const;
+    status_t readFromHalOutputFmq(size_t samplesWritten) const;
+
     // The destructor automatically releases the effect.
     virtual ~EffectHalAidl();
 };
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
index 740bf60..2753906 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -42,6 +42,8 @@
 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::AudioDevice;
+using ::aidl::android::media::audio::common::AudioDeviceAddress;
 using ::aidl::android::media::audio::common::AudioSource;
 using ::aidl::android::media::audio::common::AudioStreamType;
 using ::aidl::android::media::audio::common::AudioUuid;
@@ -281,7 +283,8 @@
 
     auto getConfigProcessingWithAidlProcessing =
             [&](const auto& aidlProcess, std::vector<effectsConfig::InputStream>& preprocess,
-                std::vector<effectsConfig::OutputStream>& postprocess) {
+                std::vector<effectsConfig::OutputStream>& postprocess,
+                std::vector<effectsConfig::DeviceEffects>& deviceprocess) {
                 if (aidlProcess.type.getTag() == Processing::Type::streamType) {
                     AudioStreamType aidlType =
                             aidlProcess.type.template get<Processing::Type::streamType>();
@@ -313,6 +316,25 @@
                     effectsConfig::InputStream stream = {.type = type.value(),
                                                          .effects = std::move(effects)};
                     preprocess.emplace_back(stream);
+                } else if (aidlProcess.type.getTag() == Processing::Type::device) {
+                    AudioDevice aidlDevice =
+                            aidlProcess.type.template get<Processing::Type::device>();
+                    std::vector<std::shared_ptr<const effectsConfig::Effect>> effects;
+                    std::transform(aidlProcess.ids.begin(), aidlProcess.ids.end(),
+                                   std::back_inserter(effects), getConfigEffectWithDescriptor);
+                    audio_devices_t type;
+                    char address[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+                    status_t status = ::aidl::android::aidl2legacy_AudioDevice_audio_device(
+                            aidlDevice, &type, address);
+                    if (status != NO_ERROR) {
+                        ALOGE("%s device effect has invalid device type / address", __func__);
+                        return;
+                    }
+                    effectsConfig::DeviceEffects device = {
+                            {.type = type, .effects = std::move(effects)},
+                            .address = address,
+                    };
+                    deviceprocess.emplace_back(device);
                 }
             };
 
@@ -320,17 +342,21 @@
             [&]() -> std::shared_ptr<const effectsConfig::Processings> {
                 std::vector<effectsConfig::InputStream> preprocess;
                 std::vector<effectsConfig::OutputStream> postprocess;
+                std::vector<effectsConfig::DeviceEffects> deviceprocess;
                 for (const auto& processing : mAidlProcessings) {
-                    getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess);
+                    getConfigProcessingWithAidlProcessing(processing, preprocess, postprocess,
+                                                          deviceprocess);
                 }
 
-                if (0 == preprocess.size() && 0 == postprocess.size()) {
+                if (0 == preprocess.size() && 0 == postprocess.size() &&
+                    0 == deviceprocess.size()) {
                     return nullptr;
                 }
 
                 return std::make_shared<const effectsConfig::Processings>(
                         effectsConfig::Processings({.preprocess = std::move(preprocess),
-                                                    .postprocess = std::move(postprocess)}));
+                                                    .postprocess = std::move(postprocess),
+                                                    .deviceprocess = std::move(deviceprocess)}));
             }());
 
     return processings;
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.cpp b/media/libaudiohal/impl/Hal2AidlMapper.cpp
index a01ac4b..f352849 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.cpp
+++ b/media/libaudiohal/impl/Hal2AidlMapper.cpp
@@ -25,6 +25,7 @@
 #include <Utils.h>
 #include <utils/Log.h>
 
+#include "AidlUtils.h"
 #include "Hal2AidlMapper.h"
 
 using aidl::android::aidl_utils::statusTFromBinderStatus;
@@ -99,8 +100,7 @@
 }  // namespace
 
 Hal2AidlMapper::Hal2AidlMapper(const std::string& instance, const std::shared_ptr<IModule>& module)
-        : mInstance(instance), mModule(module) {
-}
+    : ConversionHelperAidl("Hal2AidlMapper", instance), mModule(module) {}
 
 void Hal2AidlMapper::addStream(
         const sp<StreamHalInterface>& stream, int32_t mixPortConfigId, int32_t patchId) {
@@ -137,9 +137,9 @@
     // 'sinks' will not be updated because 'setAudioPatch' only needs IDs. Here we log
     // the source arguments, where only the audio configuration and device specifications
     // are relevant.
-    ALOGD("%s: patch ID: %d, [disregard IDs] sources: %s, sinks: %s",
-            __func__, *patchId, ::android::internal::ToString(sources).c_str(),
-            ::android::internal::ToString(sinks).c_str());
+    AUGMENT_LOG(D, "patch ID: %d, [disregard IDs] sources: %s, sinks: %s", *patchId,
+                ::android::internal::ToString(sources).c_str(),
+                ::android::internal::ToString(sinks).c_str());
     auto fillPortConfigs = [&](
             const std::vector<AudioPortConfig>& configs,
             const std::set<int32_t>& destinationPortIds,
@@ -152,18 +152,20 @@
                     // See b/315528763. Despite that the framework knows the actual format of
                     // the mix port, it still uses the original format. Luckily, there is
                     // the I/O handle which can be used to find the mix port.
-                    ALOGI("fillPortConfigs: retrying to find a mix port config with default "
-                            "configuration");
+                    AUGMENT_LOG(I,
+                                "fillPortConfigs: retrying to find a mix port config with"
+                                " default configuration");
                     if (auto it = findPortConfig(std::nullopt, s.flags,
                                     s.ext.get<AudioPortExt::mix>().handle);
                             it != mPortConfigs.end()) {
                         portConfig = it->second;
                     } else {
-                        const std::string flags = s.flags.has_value() ?
-                                s.flags->toString() : "<unspecified>";
-                        ALOGE("fillPortConfigs: existing port config for flags %s, handle %d "
-                                "not found in module %s", flags.c_str(),
-                                s.ext.get<AudioPortExt::mix>().handle, mInstance.c_str());
+                        const std::string flags =
+                                s.flags.has_value() ? s.flags->toString() : "<unspecified>";
+                        AUGMENT_LOG(E,
+                                    "fillPortConfigs: existing port config for flags %s, "
+                                    " handle %d not found",
+                                    flags.c_str(), s.ext.get<AudioPortExt::mix>().handle);
                         return BAD_VALUE;
                     }
                 } else {
@@ -171,8 +173,8 @@
                 }
             }
             LOG_ALWAYS_FATAL_IF(portConfig.id == 0,
-                    "fillPortConfigs: initial config: %s, port config: %s",
-                    s.toString().c_str(), portConfig.toString().c_str());
+                                "fillPortConfigs: initial config: %s, port config: %s",
+                                s.toString().c_str(), portConfig.toString().c_str());
             ids->push_back(portConfig.id);
             if (portIds != nullptr) {
                 portIds->insert(portConfig.portId);
@@ -218,8 +220,8 @@
         if (!created) {
             requestedPatch.id = patch.id;
             if (patch != requestedPatch) {
-                ALOGI("%s: Updating transient patch. Current: %s, new: %s",
-                        __func__, patch.toString().c_str(), requestedPatch.toString().c_str());
+                AUGMENT_LOG(I, "Updating transient patch. Current: %s, new: %s",
+                            patch.toString().c_str(), requestedPatch.toString().c_str());
                 // Since matching may be done by mix port only, update the patch if the device port
                 // config has changed.
                 patch = requestedPatch;
@@ -252,7 +254,7 @@
     int32_t id = result->id;
     if (requestedPortConfig.id != 0 && requestedPortConfig.id != id) {
         LOG_ALWAYS_FATAL("%s: requested port config id %d changed to %d", __func__,
-                requestedPortConfig.id, id);
+                         requestedPortConfig.id, id);
     }
 
     auto [_, inserted] = mPortConfigs.insert_or_assign(id, *result);
@@ -272,8 +274,8 @@
         RETURN_STATUS_IF_ERROR(createOrUpdatePortConfig(suggestedOrAppliedPortConfig,
                         &appliedPortConfig, created));
         if (appliedPortConfig.id == 0) {
-            ALOGE("%s: module %s did not apply suggested config %s", __func__,
-                    mInstance.c_str(), suggestedOrAppliedPortConfig.toString().c_str());
+            AUGMENT_LOG(E, "did not apply suggested config %s",
+                        suggestedOrAppliedPortConfig.toString().c_str());
             return NO_INIT;
         }
         *result = appliedPortConfig;
@@ -289,7 +291,7 @@
     if (mDisconnectedPortReplacement.first == portId) {
         const auto& port = mDisconnectedPortReplacement.second;
         mPorts.insert(std::make_pair(port.id, port));
-        ALOGD("%s: disconnected port replacement: %s", __func__, port.toString().c_str());
+        AUGMENT_LOG(D, "disconnected port replacement: %s", port.toString().c_str());
         mDisconnectedPortReplacement = std::pair<int32_t, AudioPort>();
     }
     updateDynamicMixPorts();
@@ -331,8 +333,7 @@
     if (auto portConfigIt = findPortConfig(device); portConfigIt == mPortConfigs.end()) {
         auto portsIt = findPort(device);
         if (portsIt == mPorts.end()) {
-            ALOGE("%s: device port for device %s is not found in the module %s",
-                    __func__, device.toString().c_str(), mInstance.c_str());
+            AUGMENT_LOG(E, "device port for device %s is not found", device.toString().c_str());
             return BAD_VALUE;
         }
         AudioPortConfig requestedPortConfig;
@@ -385,15 +386,15 @@
             matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
                     ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
             portsIt = findPort(config, matchFlags, destinationPortIds);
-            ALOGI("%s: mix port for config %s, flags %s was not found in the module %s, "
-                    "retried with flags %s", __func__, config.toString().c_str(),
-                    flags.value().toString().c_str(), mInstance.c_str(),
-                    matchFlags.toString().c_str());
+            AUGMENT_LOG(I,
+                        "mix port for config %s, flags %s was not found"
+                        "retried with flags %s",
+                        config.toString().c_str(), flags.value().toString().c_str(),
+                        matchFlags.toString().c_str());
         }
         if (portsIt == mPorts.end()) {
-            ALOGE("%s: mix port for config %s, flags %s is not found in the module %s",
-                    __func__, config.toString().c_str(), matchFlags.toString().c_str(),
-                    mInstance.c_str());
+            AUGMENT_LOG(E, "mix port for config %s, flags %s is not found",
+                        config.toString().c_str(), matchFlags.toString().c_str());
             return BAD_VALUE;
         }
         AudioPortConfig requestedPortConfig;
@@ -408,9 +409,10 @@
         }
         return createOrUpdatePortConfig(requestedPortConfig, portConfig, created);
     } else if (portConfigIt == mPortConfigs.end() && !flags.has_value()) {
-        ALOGW("%s: mix port config for %s, handle %d not found in the module %s, "
-                "and was not created as flags are not specified",
-                __func__, config.toString().c_str(), ioHandle, mInstance.c_str());
+        AUGMENT_LOG(W,
+                    "mix port config for %s, handle %d not found "
+                    "and was not created as flags are not specified",
+                    config.toString().c_str(), ioHandle);
         return BAD_VALUE;
     } else {
         AudioPortConfig requestedPortConfig = portConfigIt->second;
@@ -440,8 +442,8 @@
         if (const auto& p = requestedPortConfig;
                 !p.sampleRate.has_value() || !p.channelMask.has_value() ||
                 !p.format.has_value()) {
-            ALOGW("%s: provided mix port config is not fully specified: %s",
-                    __func__, p.toString().c_str());
+            AUGMENT_LOG(W, "provided mix port config is not fully specified: %s",
+                        p.toString().c_str());
             return BAD_VALUE;
         }
         AudioConfig config;
@@ -470,14 +472,13 @@
                     requestedPortConfig.ext.get<Tag::device>().device, configPtr, gainConfigPtr,
                     portConfig, created);
         } else {
-            ALOGD("%s: device port config does not have audio or gain config specified", __func__);
+            AUGMENT_LOG(D, "device port config does not have audio or gain config specified");
             return findOrCreateDevicePortConfig(
                     requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
                     nullptr /*gainConfig*/, portConfig, created);
         }
     }
-    ALOGW("%s: unsupported audio port config: %s",
-            __func__, requestedPortConfig.toString().c_str());
+    AUGMENT_LOG(W, "unsupported audio port config: %s", requestedPortConfig.toString().c_str());
     return BAD_VALUE;
 }
 
@@ -486,8 +487,7 @@
         *portConfig = it->second;
         return OK;
     }
-    ALOGE("%s: could not find a device port config for device %s",
-            __func__, device.toString().c_str());
+    AUGMENT_LOG(E, "could not find a device port config for device %s", device.toString().c_str());
     return BAD_VALUE;
 }
 
@@ -593,9 +593,10 @@
             }
             optionalFlags |= makeBitPositionFlagMask(*optionalOutputFlagsIt++);
             result = std::find_if(mPorts.begin(), mPorts.end(), matcher);
-            ALOGI("%s: port for config %s, flags %s was not found in the module %s, "
-                  "retried with excluding optional flags %#x", __func__, config.toString().c_str(),
-                    flags.toString().c_str(), mInstance.c_str(), optionalFlags);
+            AUGMENT_LOG(I,
+                        "port for config %s, flags %s was not found "
+                        "retried with excluding optional flags %#x",
+                        config.toString().c_str(), flags.toString().c_str(), optionalFlags);
         }
     }
     return result;
@@ -629,7 +630,7 @@
 status_t Hal2AidlMapper::getAudioMixPort(int32_t ioHandle, AudioPort* port) {
     auto it = findPortConfig(std::nullopt /*config*/, std::nullopt /*flags*/, ioHandle);
     if (it == mPortConfigs.end()) {
-        ALOGE("%s, cannot find mix port config for handle %u", __func__, ioHandle);
+        AUGMENT_LOG(E, "cannot find mix port config for handle %u", ioHandle);
         return BAD_VALUE;
     }
     return updateAudioPort(it->second.portId, port);
@@ -638,21 +639,18 @@
 status_t Hal2AidlMapper::getAudioPortCached(
         const ::aidl::android::media::audio::common::AudioDevice& device,
         ::aidl::android::media::audio::common::AudioPort* port) {
-
     if (auto portsIt = findPort(device); portsIt != mPorts.end()) {
         *port = portsIt->second;
         return OK;
     }
-    ALOGE("%s: device port for device %s is not found in the module %s",
-            __func__, device.toString().c_str(), mInstance.c_str());
+    AUGMENT_LOG(E, "device port for device %s is not found", device.toString().c_str());
     return BAD_VALUE;
 }
 
 status_t Hal2AidlMapper::initialize() {
     std::vector<AudioPort> ports;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->getAudioPorts(&ports)));
-    ALOGW_IF(ports.empty(), "%s: module %s returned an empty list of audio ports",
-            __func__, mInstance.c_str());
+    AUGMENT_LOG_IF(W, ports.empty(), "returned an empty list of audio ports");
     mDefaultInputPortId = mDefaultOutputPortId = -1;
     const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
     for (auto it = ports.begin(); it != ports.end(); ) {
@@ -685,8 +683,9 @@
         }
     }
     if (mRemoteSubmixIn.has_value() != mRemoteSubmixOut.has_value()) {
-        ALOGE("%s: The configuration only has input or output remote submix device, must have both",
-                __func__);
+        AUGMENT_LOG(E,
+                    "The configuration only has input or output remote submix device, "
+                    "must have both");
         mRemoteSubmixIn.reset();
         mRemoteSubmixOut.reset();
     }
@@ -694,7 +693,7 @@
         AudioPort connectedRSubmixIn = *mRemoteSubmixIn;
         connectedRSubmixIn.ext.get<AudioPortExt::Tag::device>().device.address =
                 AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS;
-        ALOGD("%s: connecting remote submix input", __func__);
+        AUGMENT_LOG(D, "connecting remote submix input");
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
                                 connectedRSubmixIn, &connectedRSubmixIn)));
         // The template port for the remote submix input couldn't be "default" because it is not
@@ -711,7 +710,7 @@
         AudioPort tempConnectedRSubmixOut = *mRemoteSubmixOut;
         tempConnectedRSubmixOut.ext.get<AudioPortExt::Tag::device>().device.address =
                 AUDIO_REMOTE_SUBMIX_DEVICE_ADDRESS;
-        ALOGD("%s: temporarily connecting and disconnecting remote submix output", __func__);
+        AUGMENT_LOG(D, "temporarily connecting and disconnecting remote submix output");
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
                                 tempConnectedRSubmixOut, &tempConnectedRSubmixOut)));
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->disconnectExternalDevice(
@@ -720,8 +719,8 @@
         ports.push_back(std::move(tempConnectedRSubmixOut));
     }
 
-    ALOGI("%s: module %s default port ids: input %d, output %d",
-            __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+    AUGMENT_LOG(I, "default port ids: input %d, output %d", mDefaultInputPortId,
+                mDefaultOutputPortId);
     std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
             [](const auto& p) { return std::make_pair(p.id, p); });
     RETURN_STATUS_IF_ERROR(updateRoutes());
@@ -774,10 +773,10 @@
         int32_t ioHandle, const AudioDevice& device, const AudioIoFlags& flags,
         AudioSource source, Cleanups* cleanups, AudioConfig* config,
         AudioPortConfig* mixPortConfig, AudioPatch* patch) {
-    ALOGD("%p %s: handle %d, device %s, flags %s, source %s, config %s, mix port config %s",
-            this, __func__, ioHandle, device.toString().c_str(),
-            flags.toString().c_str(), toString(source).c_str(),
-            config->toString().c_str(), mixPortConfig->toString().c_str());
+    AUGMENT_LOG(D, "handle %d, device %s, flags %s, source %s, config %s, mixport config %s",
+                ioHandle, device.toString().c_str(), flags.toString().c_str(),
+                toString(source).c_str(), config->toString().c_str(),
+                mixPortConfig->toString().c_str());
     resetUnusedPatchesAndPortConfigs();
     const AudioConfig initialConfig = *config;
     // Find / create AudioPortConfigs for the device port and the mix port,
@@ -800,8 +799,8 @@
         // module can't perform audio stream conversions.
         AudioConfig deviceConfig = initialConfig;
         if (setConfigFromPortConfig(&deviceConfig, devicePortConfig)->base != initialConfig.base) {
-            ALOGD("%s: retrying with device port config: %s", __func__,
-                    devicePortConfig.toString().c_str());
+            AUGMENT_LOG(D, "retrying with device port config: %s",
+                        devicePortConfig.toString().c_str());
             status = prepareToOpenStreamHelper(ioHandle, devicePortConfig.portId,
                     devicePortConfig.id, flags, source, initialConfig, cleanups,
                     &deviceConfig, mixPortConfig, patch);
@@ -845,8 +844,8 @@
         retryWithSuggestedConfig = true;
     }
     if (mixPortConfig->id == 0 && retryWithSuggestedConfig) {
-        ALOGD("%s: retrying to find/create a mix port config using config %s", __func__,
-                config->toString().c_str());
+        AUGMENT_LOG(D, "retrying to find/create a mix port config using config %s",
+                    config->toString().c_str());
         RETURN_STATUS_IF_ERROR(findOrCreateMixPortConfig(*config, flags, ioHandle, source,
                         std::set<int32_t>{devicePortId}, mixPortConfig, &created));
         if (created) {
@@ -855,8 +854,8 @@
         setConfigFromPortConfig(config, *mixPortConfig);
     }
     if (mixPortConfig->id == 0) {
-        ALOGD("%p %s: returning suggested config for the stream: %s", this, __func__,
-                config->toString().c_str());
+        AUGMENT_LOG(D, "returning suggested config for the stream: %s",
+                    config->toString().c_str());
         return OK;
     }
     if (isInput) {
@@ -894,9 +893,10 @@
 // Note: does not reset port configs.
 status_t Hal2AidlMapper::releaseAudioPatch(Patches::iterator it) {
     const int32_t patchId = it->first;
+    AUGMENT_LOG(D, "patchId %d", patchId);
     if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
-        ALOGE("%s: error while resetting patch %d: %s",
-                __func__, patchId, status.getDescription().c_str());
+        AUGMENT_LOG(E, "error while resetting patch %d: %s", patchId,
+                    status.getDescription().c_str());
         return statusTFromBinderStatus(status);
     }
     mPatches.erase(it);
@@ -915,7 +915,7 @@
         if (auto it = mPatches.find(patchId); it != mPatches.end()) {
             releaseAudioPatch(it);
         } else {
-            ALOGE("%s: patch id %d not found", __func__, patchId);
+            AUGMENT_LOG(E, "patch id %d not found", patchId);
             result = BAD_VALUE;
         }
     }
@@ -925,16 +925,17 @@
 
 void Hal2AidlMapper::resetPortConfig(int32_t portConfigId) {
     if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
+        AUGMENT_LOG(D, "%s", it->second.toString().c_str());
         if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
                 !status.isOk()) {
-            ALOGE("%s: error while resetting port config %d: %s",
-                    __func__, portConfigId, status.getDescription().c_str());
+            AUGMENT_LOG(E, "error while resetting port config %d: %s", portConfigId,
+                        status.getDescription().c_str());
             return;
         }
         mPortConfigs.erase(it);
         return;
     }
-    ALOGE("%s: port config id %d not found", __func__, portConfigId);
+    AUGMENT_LOG(E, "port config id %d not found", portConfigId);
 }
 
 void Hal2AidlMapper::resetUnusedPatchesAndPortConfigs() {
@@ -979,6 +980,8 @@
 }
 
 status_t Hal2AidlMapper::setDevicePortConnectedState(const AudioPort& devicePort, bool connected) {
+    AUGMENT_LOG(D, "state %s, device %s", (connected ? "connected" : "disconnected"),
+                devicePort.toString().c_str());
     resetUnusedPatchesAndPortConfigs();
     if (connected) {
         AudioDevice matchDevice = devicePort.ext.get<AudioPortExt::device>().device;
@@ -1009,8 +1012,7 @@
                 // port not found in every one of them.
                 return BAD_VALUE;
             } else {
-                ALOGD("%s: device port for device %s found in the module %s",
-                        __func__, matchDevice.toString().c_str(), mInstance.c_str());
+                AUGMENT_LOG(D, "device port for device %s found", matchDevice.toString().c_str());
             }
             templatePort = portsIt->second;
         }
@@ -1021,10 +1023,9 @@
         RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->connectExternalDevice(
                                 connectedPort, &connectedPort)));
         const auto [it, inserted] = mPorts.insert(std::make_pair(connectedPort.id, connectedPort));
-        LOG_ALWAYS_FATAL_IF(!inserted,
-                "%s: module %s, duplicate port ID received from HAL: %s, existing port: %s",
-                __func__, mInstance.c_str(), connectedPort.toString().c_str(),
-                it->second.toString().c_str());
+        LOG_ALWAYS_FATAL_IF(
+                !inserted, "%s duplicate port ID received from HAL: %s, existing port: %s",
+                __func__, connectedPort.toString().c_str(), it->second.toString().c_str());
         mConnectedPorts.insert(connectedPort.id);
         if (erasePortAfterConnectionIt != mPorts.end()) {
             mPorts.erase(erasePortAfterConnectionIt);
@@ -1037,8 +1038,7 @@
             // port not found in every one of them.
             return BAD_VALUE;
         } else {
-            ALOGD("%s: device port for device %s found in the module %s",
-                    __func__, matchDevice.toString().c_str(), mInstance.c_str());
+            AUGMENT_LOG(D, "device port for device %s found", matchDevice.toString().c_str());
         }
 
         // Disconnection of remote submix out with address "0" is a special case. We need to replace
@@ -1094,8 +1094,8 @@
             }
             portIt->second = *port;
         } else {
-            ALOGW("%s, port(%d) returned successfully from the HAL but not it is not cached",
-                  __func__, portId);
+            AUGMENT_LOG(W, "port(%d) returned successfully from the HAL but not it is not cached",
+                        portId);
         }
     }
     return status;
@@ -1104,8 +1104,7 @@
 status_t Hal2AidlMapper::updateRoutes() {
     RETURN_STATUS_IF_ERROR(
             statusTFromBinderStatus(mModule->getAudioRoutes(&mRoutes)));
-    ALOGW_IF(mRoutes.empty(), "%s: module %s returned an empty list of audio routes",
-            __func__, mInstance.c_str());
+    AUGMENT_LOG_IF(W, mRoutes.empty(), "returned an empty list of audio routes");
     if (mRemoteSubmixIn.has_value()) {
         // Remove mentions of the template remote submix input from routes.
         int32_t rSubmixInId = mRemoteSubmixIn->id;
@@ -1146,7 +1145,7 @@
             updateAudioPort(portId, &it->second);
         } else {
             // This must not happen
-            ALOGE("%s, cannot find port for id=%d", __func__, portId);
+            AUGMENT_LOG(E, "cannot find port for id=%d", portId);
         }
     }
 }
diff --git a/media/libaudiohal/impl/Hal2AidlMapper.h b/media/libaudiohal/impl/Hal2AidlMapper.h
index 710b43e..2548752 100644
--- a/media/libaudiohal/impl/Hal2AidlMapper.h
+++ b/media/libaudiohal/impl/Hal2AidlMapper.h
@@ -26,6 +26,7 @@
 #include <media/AidlConversionUtil.h>
 
 #include "Cleanups.h"
+#include "ConversionHelperAidl.h"
 
 namespace android {
 
@@ -41,7 +42,7 @@
 // but still consider some of the outputs to be valid (for example, in 'open{Input|Output}Stream'),
 // 'Hal2AidlMapper' follows the Binder convention. It means that if a method returns an error,
 // the outputs may not be initialized at all and should not be considered by the caller.
-class Hal2AidlMapper {
+class Hal2AidlMapper : public ConversionHelperAidl {
   public:
     using Cleanups = Cleanups<Hal2AidlMapper>;
 
@@ -135,7 +136,6 @@
 
     enum PatchMatch { MATCH_SOURCES, MATCH_SINKS, MATCH_BOTH };
 
-    const std::string mInstance;
     const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
 
     bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
index 030ee2b..d65701a 100644
--- a/media/libaudiohal/impl/StreamHalAidl.cpp
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -32,6 +32,7 @@
 #include <Utils.h>
 #include <utils/Log.h>
 
+#include "AidlUtils.h"
 #include "DeviceHalAidl.h"
 #include "EffectHalAidl.h"
 #include "StreamHalAidl.h"
@@ -58,6 +59,16 @@
 template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) {
     return HalCommand::make<cmd>(data);
 }
+
+template <typename MQTypeError>
+auto fmqErrorHandler(const char* mqName) {
+    return [m = std::string(mqName)](MQTypeError fmqError, std::string&& errorMessage) {
+        mediautils::TimeCheck::signalAudioHals();
+        LOG_ALWAYS_FATAL_IF(fmqError != MQTypeError::NONE, "%s: %s",
+                m.c_str(), errorMessage.c_str());
+    };
+}
+
 }  // namespace
 
 // static
@@ -74,12 +85,12 @@
     return streamCommon;
 }
 
-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<IHalAdapterVendorExtension>& vext)
-        : ConversionHelperAidl(className),
+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<IHalAdapterVendorExtension>& vext)
+    : ConversionHelperAidl(className, std::string(isInput ? "in" : "out") + "|ioHandle:" +
+            std::to_string(context.getIoHandle())),
           mIsInput(isInput),
           mConfig(configToBase(config)),
           mContext(std::move(context)),
@@ -90,7 +101,7 @@
                            mContext.getBufferDurationMs(mConfig.sample_rate))
                   * NANOS_PER_MILLISECOND)
 {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     {
         std::lock_guard l(mLock);
         mLastReply.latencyMs = nominalLatency;
@@ -102,18 +113,29 @@
             StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
         mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
     }
+
+    if (mStream != nullptr) {
+        mContext.getCommandMQ()->setErrorHandler(
+                fmqErrorHandler<StreamContextAidl::CommandMQ::Error>("CommandMQ"));
+        mContext.getReplyMQ()->setErrorHandler(
+                fmqErrorHandler<StreamContextAidl::ReplyMQ::Error>("ReplyMQ"));
+        if (mContext.getDataMQ() != nullptr) {
+            mContext.getDataMQ()->setErrorHandler(
+                    fmqErrorHandler<StreamContextAidl::DataMQ::Error>("DataMQ"));
+        }
+    }
 }
 
 StreamHalAidl::~StreamHalAidl() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     if (mStream != nullptr) {
         ndk::ScopedAStatus status = mStream->close();
-        ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
+        AUGMENT_LOG_IF(E, !status.isOk(), "status %s", status.getDescription().c_str());
     }
 }
 
 status_t StreamHalAidl::getBufferSize(size_t *size) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     if (size == nullptr) {
         return BAD_VALUE;
     }
@@ -122,11 +144,12 @@
         return NO_INIT;
     }
     *size = mContext.getBufferSizeBytes();
+    AUGMENT_LOG(I, "size: %zu", *size);
     return OK;
 }
 
 status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     if (configBase == nullptr) {
         return BAD_VALUE;
     }
@@ -136,10 +159,11 @@
 }
 
 status_t StreamHalAidl::setParameters(const String8& kvPairs) {
+    AUGMENT_LOG(V);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     AudioParameter parameters(kvPairs);
-    ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
+    AUGMENT_LOG(D, "parameters: %s", parameters.toString().c_str());
 
     (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
                     parameters, String8(AudioParameter::keyStreamHwAvSync),
@@ -150,6 +174,7 @@
 }
 
 status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+    AUGMENT_LOG(V);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (values == nullptr) {
@@ -161,7 +186,7 @@
 }
 
 status_t StreamHalAidl::getFrameSize(size_t *size) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     if (size == nullptr) {
         return BAD_VALUE;
     }
@@ -173,7 +198,7 @@
 }
 
 status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (effect == nullptr) {
@@ -184,7 +209,7 @@
 }
 
 status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (effect == nullptr) {
@@ -195,7 +220,7 @@
 }
 
 status_t StreamHalAidl::standby() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     const auto state = getState();
@@ -208,8 +233,8 @@
             if (reply.state != StreamDescriptor::State::PAUSED &&
                     reply.state != StreamDescriptor::State::DRAIN_PAUSED &&
                     reply.state != StreamDescriptor::State::TRANSFER_PAUSED) {
-                ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
-                        __func__, toString(reply.state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected PAUSED)",
+                            toString(reply.state).c_str());
                 return INVALID_OPERATION;
             }
             FALLTHROUGH_INTENDED;
@@ -219,8 +244,8 @@
             if (mIsInput) return flush();
             RETURN_STATUS_IF_ERROR(flush(&reply));
             if (reply.state != StreamDescriptor::State::IDLE) {
-                ALOGE("%s: unexpected stream state: %s (expected IDLE)",
-                        __func__, toString(reply.state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected IDLE)",
+                            toString(reply.state).c_str());
                 return INVALID_OPERATION;
             }
             FALLTHROUGH_INTENDED;
@@ -228,22 +253,22 @@
             RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
                             &reply, true /*safeFromNonWorkerThread*/));
             if (reply.state != StreamDescriptor::State::STANDBY) {
-                ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
-                        __func__, toString(reply.state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected STANDBY)",
+                            toString(reply.state).c_str());
                 return INVALID_OPERATION;
             }
             FALLTHROUGH_INTENDED;
         case StreamDescriptor::State::STANDBY:
             return OK;
         default:
-            ALOGE("%s: not supported from %s stream state %s",
-                    __func__, mIsInput ? "input" : "output", toString(state).c_str());
+            AUGMENT_LOG(E, "not supported from %s stream state %s", mIsInput ? "input" : "output",
+                        toString(state).c_str());
             return INVALID_OPERATION;
     }
 }
 
 status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     Vector<String16> newArgs = args;
@@ -254,7 +279,7 @@
 }
 
 status_t StreamHalAidl::start() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (!mContext.isMmapped()) {
@@ -267,8 +292,8 @@
             RETURN_STATUS_IF_ERROR(
                     sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true));
             if (reply.state != StreamDescriptor::State::IDLE) {
-                ALOGE("%s: unexpected stream state: %s (expected IDLE)",
-                        __func__, toString(reply.state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected IDLE)",
+                            toString(reply.state).c_str());
                 return INVALID_OPERATION;
             }
             FALLTHROUGH_INTENDED;
@@ -276,8 +301,8 @@
             RETURN_STATUS_IF_ERROR(
                     sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), &reply, true));
             if (reply.state != StreamDescriptor::State::ACTIVE) {
-                ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
-                        __func__, toString(reply.state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected ACTIVE)",
+                            toString(reply.state).c_str());
                 return INVALID_OPERATION;
             }
             FALLTHROUGH_INTENDED;
@@ -287,20 +312,20 @@
             RETURN_STATUS_IF_ERROR(
                     sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply, true));
             if (reply.state != StreamDescriptor::State::ACTIVE) {
-                ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
-                        __func__, toString(reply.state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected ACTIVE)",
+                            toString(reply.state).c_str());
                 return INVALID_OPERATION;
             }
             return OK;
         default:
-            ALOGE("%s: not supported from %s stream state %s",
-                    __func__, mIsInput ? "input" : "output", toString(reply.state).c_str());
+            AUGMENT_LOG(E, "not supported from %s stream state %s", mIsInput ? "input" : "output",
+                        toString(reply.state).c_str());
             return INVALID_OPERATION;
     }
 }
 
 status_t StreamHalAidl::stop() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (!mContext.isMmapped()) {
@@ -317,28 +342,28 @@
         return flush();
     } else if (state != StreamDescriptor::State::IDLE &&
             state != StreamDescriptor::State::STANDBY) {
-        ALOGE("%s: not supported from %s stream state %s",
-                __func__, mIsInput ? "input" : "output", toString(state).c_str());
+        AUGMENT_LOG(E, "not supported from %s stream state %s", mIsInput ? "input" : "output",
+                    toString(state).c_str());
         return INVALID_OPERATION;
     }
     return OK;
 }
 
 status_t StreamHalAidl::getLatency(uint32_t *latency) {
-    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     if (!mStream) return NO_INIT;
     StreamDescriptor::Reply reply;
     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
     *latency = std::clamp(std::max<int32_t>(0, reply.latencyMs), 1, 3000);
-    ALOGW_IF(reply.latencyMs != static_cast<int32_t>(*latency),
-             "Suspicious latency value reported by HAL: %d, clamped to %u", reply.latencyMs,
-             *latency);
+    AUGMENT_LOG_IF(W, reply.latencyMs != static_cast<int32_t>(*latency),
+                   "Suspicious latency value reported by HAL: %d, clamped to %u", reply.latencyMs,
+                   *latency);
     return OK;
 }
 
 status_t StreamHalAidl::getObservablePosition(int64_t* frames, int64_t* timestamp,
         StatePositions* statePositions) {
-    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     if (!mStream) return NO_INIT;
     StreamDescriptor::Reply reply;
     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply, statePositions));
@@ -348,7 +373,7 @@
 }
 
 status_t StreamHalAidl::getHardwarePosition(int64_t *frames, int64_t *timestamp) {
-    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     if (!mStream) return NO_INIT;
     StreamDescriptor::Reply reply;
     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
@@ -358,7 +383,7 @@
 }
 
 status_t StreamHalAidl::getXruns(int32_t *frames) {
-    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     if (!mStream) return NO_INIT;
     StreamDescriptor::Reply reply;
     RETURN_STATUS_IF_ERROR(updateCountersIfNeeded(&reply));
@@ -367,7 +392,7 @@
 }
 
 status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
-    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(V);
     // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
     mWorkerTid.store(gettid(), std::memory_order_release);
@@ -379,22 +404,19 @@
         StreamDescriptor::Reply reply;
         RETURN_STATUS_IF_ERROR(sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply));
         if (reply.state != StreamDescriptor::State::IDLE) {
-            ALOGE("%s: failed to get the stream out of standby, actual state: %s",
-                    __func__, toString(reply.state).c_str());
+            AUGMENT_LOG(E, "failed to get the stream out of standby, actual state: %s",
+                        toString(reply.state).c_str());
             return INVALID_OPERATION;
         }
     }
-    StreamContextAidl::DataMQ::Error fmqError = StreamContextAidl::DataMQ::Error::NONE;
-    std::string fmqErrorMsg;
     if (!mIsInput) {
-        bytes = std::min(bytes,
-                mContext.getDataMQ()->availableToWrite(&fmqError, &fmqErrorMsg));
+        bytes = std::min(bytes, mContext.getDataMQ()->availableToWrite());
     }
     StreamDescriptor::Command burst =
             StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(bytes);
     if (!mIsInput) {
         if (!mContext.getDataMQ()->write(static_cast<const int8_t*>(buffer), bytes)) {
-            ALOGE("%s: failed to write %zu bytes to data MQ", __func__, bytes);
+            AUGMENT_LOG(E, "failed to write %zu bytes to data MQ", bytes);
             return NOT_ENOUGH_DATA;
         }
     }
@@ -405,28 +427,34 @@
         LOG_ALWAYS_FATAL_IF(*transferred > bytes,
                 "%s: HAL module read %zu bytes, which exceeds requested count %zu",
                 __func__, *transferred, bytes);
-        if (auto toRead = mContext.getDataMQ()->availableToRead(&fmqError, &fmqErrorMsg);
+        if (auto toRead = mContext.getDataMQ()->availableToRead();
                 toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
-            ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
+            AUGMENT_LOG(E, "failed to read %zu bytes to data MQ", toRead);
             return NOT_ENOUGH_DATA;
         }
     }
-    LOG_ALWAYS_FATAL_IF(fmqError != StreamContextAidl::DataMQ::Error::NONE,
-            "%s", fmqErrorMsg.c_str());
     mStreamPowerLog.log(buffer, *transferred);
     return OK;
 }
 
 status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
-            true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
+
+    if (const auto state = getState(); isInPlayOrRecordState(state)) {
+        return sendCommand(
+                makeHalCommand<HalCommand::Tag::pause>(), reply,
+                true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
+    } else {
+        AUGMENT_LOG(D, "already stream in one of the PAUSED kind of states, current state: %s",
+                toString(state).c_str());
+        return OK;
+    }
 }
 
 status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (mIsInput) {
@@ -440,8 +468,8 @@
             RETURN_STATUS_IF_ERROR(
                     sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply));
             if (innerReply->state != StreamDescriptor::State::ACTIVE) {
-                ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
-                        __func__, toString(innerReply->state).c_str());
+                AUGMENT_LOG(E, "unexpected stream state: %s (expected ACTIVE)",
+                            toString(innerReply->state).c_str());
                 return INVALID_OPERATION;
             }
             return OK;
@@ -452,18 +480,18 @@
         } else if (state == StreamDescriptor::State::ACTIVE ||
                    state == StreamDescriptor::State::TRANSFERRING ||
                    state == StreamDescriptor::State::DRAINING) {
-            ALOGD("%s: already in stream state: %s", __func__, toString(state).c_str());
+            AUGMENT_LOG(D, "already in stream state: %s", toString(state).c_str());
             return OK;
         } else {
-            ALOGE("%s: unexpected stream state: %s (expected IDLE or one of *PAUSED states)",
-                        __func__, toString(state).c_str());
+            AUGMENT_LOG(E, "unexpected stream state: %s (expected IDLE or one of *PAUSED states)",
+                        toString(state).c_str());
             return INVALID_OPERATION;
         }
     }
 }
 
 status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
@@ -474,15 +502,26 @@
 }
 
 status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
-    return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
-            true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
+
+    if (const auto state = getState(); isInPausedState(state)) {
+        return sendCommand(
+                makeHalCommand<HalCommand::Tag::flush>(), reply,
+                true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
+    } else if (isInPlayOrRecordState(state)) {
+        AUGMENT_LOG(E, "found stream in non-flushable state: %s", toString(state).c_str());
+        return INVALID_OPERATION;
+    } else {
+        AUGMENT_LOG(D, "already stream in one of the flushable state: current state: %s",
+                    toString(state).c_str());
+        return OK;
+    }
 }
 
 status_t StreamHalAidl::exit() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     return statusTFromBinderStatus(mStream->prepareToClose());
@@ -495,7 +534,7 @@
         sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(),
                 nullptr, true /*safeFromNonWorkerThread */);
     } else {
-        ALOGW("%s: unexpected onTransferReady in the state %s", __func__, toString(state).c_str());
+        AUGMENT_LOG(W, "unexpected onTransferReady in the state %s", toString(state).c_str());
     }
 }
 
@@ -510,19 +549,19 @@
         std::lock_guard l(mLock);
         mStatePositions.framesAtFlushOrDrain = mLastReply.observable.frames;
     } else {
-        ALOGW("%s: unexpected onDrainReady in the state %s", __func__, toString(state).c_str());
+        AUGMENT_LOG(W, "unexpected onDrainReady in the state %s", toString(state).c_str());
     }
 }
 
 void StreamHalAidl::onAsyncError() {
     std::lock_guard l(mLock);
-    ALOGW("%s: received in the state %s", __func__, toString(mLastReply.state).c_str());
+    AUGMENT_LOG(W, "received in the state %s", toString(mLastReply.state).c_str());
     mLastReply.state = StreamDescriptor::State::ERROR;
 }
 
 status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
                                          struct audio_mmap_buffer_info *info) {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (!mContext.isMmapped()) {
@@ -582,15 +621,14 @@
     {
         std::lock_guard l(mCommandReplyLock);
         if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
-            ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
+            AUGMENT_LOG(E, "failed to write command %s to MQ", command.toString().c_str());
             return NOT_ENOUGH_DATA;
         }
         if (reply == nullptr) {
             reply = &localReply;
         }
         if (!mContext.getReplyMQ()->readBlocking(reply, 1)) {
-            ALOGE("%s: failed to read from reply MQ, command %s",
-                    __func__, command.toString().c_str());
+            AUGMENT_LOG(E, "failed to read from reply MQ, command %s", command.toString().c_str());
             return NOT_ENOUGH_DATA;
         }
         {
@@ -627,8 +665,8 @@
         case STATUS_INVALID_OPERATION: return INVALID_OPERATION;
         case STATUS_NOT_ENOUGH_DATA: return NOT_ENOUGH_DATA;
         default:
-            ALOGE("%s: unexpected status %d returned for command %s",
-                    __func__, reply->status, command.toString().c_str());
+            AUGMENT_LOG(E, "unexpected status %d returned for command %s", reply->status,
+                        command.toString().c_str());
             return INVALID_OPERATION;
     }
 }
@@ -693,10 +731,10 @@
     if (!mStream) return NO_INIT;
 
     AudioParameter parameters(kvPairs);
-    ALOGD("%s: parameters: \"%s\"", __func__, parameters.toString().c_str());
+    AUGMENT_LOG(D, "parameters: \"%s\"", parameters.toString().c_str());
 
     if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
-        ALOGW("%s: filtering or updating offload metadata failed: %d", __func__, status);
+        AUGMENT_LOG(W, "filtering or updating offload metadata failed: %d", status);
     }
 
     return StreamHalAidl::setParameters(parameters.toString());
@@ -707,6 +745,7 @@
 }
 
 status_t StreamOutHalAidl::setVolume(float left, float right) {
+    AUGMENT_LOG(V, "left %f right %f", left, right);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     size_t channelCount = audio_channel_count_from_out_mask(mConfig.channel_mask);
@@ -760,11 +799,11 @@
 }
 
 status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
-    ALOGD("%p %s", this, __func__);
+    AUGMENT_LOG(D);
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     if (!mContext.isAsynchronous()) {
-        ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
+        AUGMENT_LOG(E, "the callback is intended for asynchronous streams only");
         return INVALID_OPERATION;
     }
     mClientCallback = callback;
@@ -802,9 +841,9 @@
 status_t StreamOutHalAidl::drain(bool earlyNotify) {
     if (!mStream) return NO_INIT;
 
-    if(const auto state = getState(); state == StreamDescriptor::State::IDLE) {
-        ALOGD("%p %s stream already in IDLE state", this, __func__);
-        if(mContext.isAsynchronous()) onDrainReady();
+    if (const auto state = getState(); isInDrainedState(state)) {
+        AUGMENT_LOG(D, "stream already in %s state", toString(state).c_str());
+        if (mContext.isAsynchronous()) onDrainReady();
         return OK;
     }
 
@@ -836,7 +875,7 @@
 }
 
 status_t StreamOutHalAidl::presentationComplete() {
-    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    AUGMENT_LOG(D);
     return OK;
 }
 
@@ -1027,10 +1066,10 @@
         updateMetadata = true;
     }
     if (updateMetadata) {
-        ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
+        AUGMENT_LOG(D, "set offload metadata %s", mOffloadMetadata.toString().c_str());
         if (status_t status = statusTFromBinderStatus(
                         mStream->updateOffloadMetadata(mOffloadMetadata)); status != OK) {
-            ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
+            AUGMENT_LOG(E, "updateOffloadMetadata failed %d", status);
             return status;
         }
     }
@@ -1117,7 +1156,7 @@
             // Note: info.portId is not filled because it's a bit of framework info.
             result.push_back(std::move(info));
         } else {
-            ALOGE("%s: no static info for active microphone with id '%s'", __func__, d.id.c_str());
+            AUGMENT_LOG(E, "no static info for active microphone with id '%s'", d.id.c_str());
         }
     }
     *microphones = std::move(result);
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
index 0587640..a1cdac4 100644
--- a/media/libaudiohal/impl/StreamHalAidl.h
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -53,7 +53,7 @@
 
     StreamContextAidl(
             ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
-            bool isAsynchronous)
+            bool isAsynchronous, int ioHandle)
         : mFrameSizeBytes(descriptor.frameSizeBytes),
           mCommandMQ(new CommandMQ(descriptor.command)),
           mReplyMQ(new ReplyMQ(descriptor.reply)),
@@ -61,7 +61,8 @@
           mDataMQ(maybeCreateDataMQ(descriptor)),
           mIsAsynchronous(isAsynchronous),
           mIsMmapped(isMmapped(descriptor)),
-          mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)) {}
+          mMmapBufferDescriptor(maybeGetMmapBuffer(descriptor)),
+          mIoHandle(ioHandle) {}
     StreamContextAidl(StreamContextAidl&& other) :
             mFrameSizeBytes(other.mFrameSizeBytes),
             mCommandMQ(std::move(other.mCommandMQ)),
@@ -70,7 +71,8 @@
             mDataMQ(std::move(other.mDataMQ)),
             mIsAsynchronous(other.mIsAsynchronous),
             mIsMmapped(other.mIsMmapped),
-            mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)) {}
+            mMmapBufferDescriptor(std::move(other.mMmapBufferDescriptor)),
+            mIoHandle(other.mIoHandle) {}
     StreamContextAidl& operator=(StreamContextAidl&& other) {
         mFrameSizeBytes = other.mFrameSizeBytes;
         mCommandMQ = std::move(other.mCommandMQ);
@@ -80,6 +82,7 @@
         mIsAsynchronous = other.mIsAsynchronous;
         mIsMmapped = other.mIsMmapped;
         mMmapBufferDescriptor = std::move(other.mMmapBufferDescriptor);
+        mIoHandle = other.mIoHandle;
         return *this;
     }
     bool isValid() const {
@@ -105,7 +108,9 @@
     bool isAsynchronous() const { return mIsAsynchronous; }
     bool isMmapped() const { return mIsMmapped; }
     const MmapBufferDescriptor& getMmapBufferDescriptor() const { return mMmapBufferDescriptor; }
-    size_t getMmapBurstSize() const { return mMmapBufferDescriptor.burstSizeFrames;}
+    size_t getMmapBurstSize() const { return mMmapBufferDescriptor.burstSizeFrames; }
+    int getIoHandle() const { return mIoHandle; }
+
   private:
     static std::unique_ptr<DataMQ> maybeCreateDataMQ(
             const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
@@ -137,6 +142,7 @@
     bool mIsAsynchronous;
     bool mIsMmapped;
     MmapBufferDescriptor mMmapBufferDescriptor;
+    int mIoHandle;
 };
 
 class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
@@ -220,6 +226,41 @@
         return mLastReply.state;
     }
 
+    bool isInDrainedState(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor::State state) {
+        if (state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::IDLE ||
+            state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::STANDBY) {
+            // drain equivalent states
+            return true;
+        }
+        return false;
+    }
+
+    bool isInPlayOrRecordState(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor::State state) {
+        if (state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::ACTIVE ||
+            state ==
+                    ::aidl::android::hardware::audio::core::StreamDescriptor::State::TRANSFERRING ||
+            state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::DRAINING) {
+            // play or record equivalent states
+            return true;
+        }
+        return false;
+    }
+
+    bool isInPausedState(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor::State& state) {
+        if (state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::PAUSED ||
+            state ==
+                    ::aidl::android::hardware::audio::core::StreamDescriptor::State::DRAIN_PAUSED ||
+            state == ::aidl::android::hardware::audio::core::StreamDescriptor::State::
+                             TRANSFER_PAUSED) {
+            // pause equivalent states
+            return true;
+        }
+        return false;
+    }
+
     status_t getLatency(uint32_t *latency);
 
     // Always returns non-negative values.
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index 7f6c1fb..3f16526 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -90,7 +90,8 @@
             audio_output_flags_t flags,
             struct audio_config *config,
             const char *address,
-            sp<StreamOutHalInterface> *outStream) = 0;
+            sp<StreamOutHalInterface> *outStream,
+            const std::vector<playback_track_metadata_v7_t>& sourceMetadata = {}) = 0;
 
     // Creates and opens the audio hardware input stream. The stream is closed
     // by releasing all references to the returned object.
diff --git a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
index 50b748e..0f5334f 100644
--- a/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
+++ b/media/libaudiohal/tests/CoreAudioHalAidl_test.cpp
@@ -18,6 +18,7 @@
 #include <memory>
 #include <mutex>
 #include <string>
+#include <thread>
 #include <vector>
 
 #define LOG_TAG "CoreAudioHalAidlTest"
@@ -28,6 +29,7 @@
 #include <StreamHalAidl.h>
 #include <aidl/android/hardware/audio/core/BnModule.h>
 #include <aidl/android/hardware/audio/core/BnStreamCommon.h>
+#include <aidl/android/hardware/audio/core/BnStreamOut.h>
 #include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
 #include <aidl/android/media/audio/common/AudioGainMode.h>
 #include <aidl/android/media/audio/common/Int.h>
@@ -64,13 +66,13 @@
     const std::vector<VendorParameter>& getSyncParameters() const { return mSyncParameters; }
 
   protected:
-    ndk::ScopedAStatus getVendorParametersImpl(const std::vector<std::string>& in_parameterIds) {
+    ndk::ScopedAStatus getVendorParameters(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) {
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool async) {
         if (async) {
             mAsyncParameters.insert(mAsyncParameters.end(), in_parameters.begin(),
                                     in_parameters.end());
@@ -187,6 +189,11 @@
     speakerOutDevice.profiles = standardPcmAudioProfiles;
     c.ports.push_back(speakerOutDevice);
 
+    AudioPort primaryOutMix =
+            createPort(c.nextPortId++, "primary output", 0, false, createPortMixExt(1, 1));
+    primaryOutMix.profiles = standardPcmAudioProfiles;
+    c.ports.push_back(primaryOutMix);
+
     AudioPort btOutDevice =
             createPort(c.nextPortId++, "BT A2DP Out", 0, false,
                        createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
@@ -200,11 +207,141 @@
     c.ports.push_back(btOutMix);
 
     c.routes.push_back(createRoute({micInDevice, micInBackDevice}, primaryInMix));
+    c.routes.push_back(createRoute({primaryOutMix}, speakerOutDevice));
     c.routes.push_back(createRoute({btOutMix}, btOutDevice));
 
     return c;
 }
 
+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 VendorParameterMock::getVendorParameters(in_parameterIds);
+    }
+    ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
+                                           bool async) override {
+        return VendorParameterMock::setVendorParameters(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();
+    }
+};
+
+class StreamContext {
+  public:
+    using Descriptor = ::aidl::android::hardware::audio::core::StreamDescriptor;
+    typedef ::android::AidlMessageQueue<
+            Descriptor::Command, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            CommandMQ;
+    typedef ::android::AidlMessageQueue<
+            Descriptor::Reply, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            ReplyMQ;
+    typedef ::android::AidlMessageQueue<
+            int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+            DataMQ;
+
+    StreamContext() = default;
+    StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
+                  std::unique_ptr<DataMQ> dataMQ)
+        : mCommandMQ(std::move(commandMQ)),
+          mReplyMQ(std::move(replyMQ)),
+          mDataMQ(std::move(dataMQ)) {}
+    void fillDescriptor(Descriptor* desc) {
+        if (mCommandMQ) {
+            desc->command = mCommandMQ->dupeDesc();
+        }
+        if (mReplyMQ) {
+            desc->reply = mReplyMQ->dupeDesc();
+        }
+        if (mDataMQ) {
+            desc->frameSizeBytes = 2;
+            desc->bufferSizeFrames = 48;
+            desc->audio.set<Descriptor::AudioBuffer::Tag::fmq>(mDataMQ->dupeDesc());
+        }
+    }
+
+  private:
+    std::unique_ptr<CommandMQ> mCommandMQ =
+            std::make_unique<CommandMQ>(1, true /*configureEventFlagWord*/);
+    std::unique_ptr<ReplyMQ> mReplyMQ =
+            std::make_unique<ReplyMQ>(1, true /*configureEventFlagWord*/);
+    std::unique_ptr<DataMQ> mDataMQ = std::make_unique<DataMQ>(96);
+};
+
+class StreamOutMock : public ::aidl::android::hardware::audio::core::BnStreamOut {
+  public:
+    explicit StreamOutMock(StreamContext&& ctx) : mContext(std::move(ctx)) {}
+
+  private:
+    ndk::ScopedAStatus getStreamCommon(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>* _aidl_return)
+            override {
+        if (!mCommon) {
+            mCommon = ndk::SharedRefBase::make<StreamCommonMock>();
+        }
+        *_aidl_return = mCommon;
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateMetadata(
+            const ::aidl::android::hardware::audio::common::SourceMetadata&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus updateOffloadMetadata(
+            const ::aidl::android::hardware::audio::common::AudioOffloadMetadata&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getHwVolume(std::vector<float>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setHwVolume(const std::vector<float>&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getAudioDescriptionMixLevel(float*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setAudioDescriptionMixLevel(float) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getDualMonoMode(
+            ::aidl::android::media::audio::common::AudioDualMonoMode*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setDualMonoMode(
+            ::aidl::android::media::audio::common::AudioDualMonoMode) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getRecommendedLatencyModes(
+            std::vector<::aidl::android::media::audio::common::AudioLatencyMode>*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setLatencyMode(
+            ::aidl::android::media::audio::common::AudioLatencyMode) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus getPlaybackRateParameters(
+            ::aidl::android::media::audio::common::AudioPlaybackRate*) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus setPlaybackRateParameters(
+            const ::aidl::android::media::audio::common::AudioPlaybackRate&) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    ndk::ScopedAStatus selectPresentation(int32_t, int32_t) override {
+        return ndk::ScopedAStatus::ok();
+    }
+    StreamContext mContext;
+    std::shared_ptr<StreamCommonMock> mCommon;
+};
+
 class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
                    public VendorParameterMock {
   public:
@@ -339,7 +476,10 @@
         return ndk::ScopedAStatus::ok();
     }
     ndk::ScopedAStatus openOutputStream(const OpenOutputStreamArguments&,
-                                        OpenOutputStreamReturn*) override {
+                                        OpenOutputStreamReturn* _aidl_return) override {
+        StreamContext context;
+        context.fillDescriptor(&_aidl_return->desc);
+        _aidl_return->stream = ndk::SharedRefBase::make<StreamOutMock>(std::move(context));
         return ndk::ScopedAStatus::ok();
     }
     ndk::ScopedAStatus getSupportedPlaybackRateFactors(SupportedPlaybackRateFactors*) override {
@@ -351,6 +491,7 @@
         if (requested.id == 0) {
             *patch = requested;
             patch->id = mConfig.nextPatchId++;
+            patch->latenciesMs.push_back(100);
             mConfig.patches.push_back(*patch);
             ALOGD("%s: returning %s", __func__, patch->toString().c_str());
         } else {
@@ -437,11 +578,11 @@
     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);
+        return VendorParameterMock::getVendorParameters(in_parameterIds);
     }
     ndk::ScopedAStatus setVendorParameters(const std::vector<VendorParameter>& in_parameters,
                                            bool async) override {
-        return setVendorParametersImpl(in_parameters, async);
+        return VendorParameterMock::setVendorParameters(in_parameters, async);
     }
     ndk::ScopedAStatus addDeviceEffect(
             int32_t,
@@ -474,29 +615,6 @@
     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,
@@ -708,7 +826,7 @@
 class DeviceHalAidlTest : public testing::Test {
   public:
     void SetUp() override {
-        mModule = ndk::SharedRefBase::make<ModuleMock>();
+        mModule = ndk::SharedRefBase::make<ModuleMock>(getTestConfiguration());
         mDevice = sp<DeviceHalAidl>::make("test", mModule, nullptr /*vext*/);
     }
     void TearDown() override {
@@ -750,6 +868,46 @@
     EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
 }
 
+// See http://b/357487484#comment6
+TEST_F(DeviceHalAidlTest, StreamReleaseOnMapperCleanup) {
+    ASSERT_EQ(OK, mDevice->initCheck());
+    // Since the test is in effect probabilistic, try multiple times.
+    for (int i = 0; i < 100; ++i) {
+        sp<StreamOutHalInterface> stream1;
+        struct audio_config config = AUDIO_CONFIG_INITIALIZER;
+        config.sample_rate = 48000;
+        config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        config.format = AUDIO_FORMAT_PCM_16_BIT;
+        ASSERT_EQ(OK, mDevice->openOutputStream(42 /*handle*/, AUDIO_DEVICE_OUT_SPEAKER,
+                                                AUDIO_OUTPUT_FLAG_NONE, &config, "" /*address*/,
+                                                &stream1));
+        ASSERT_EQ(1, stream1->getStrongCount());
+        std::atomic<bool> stopReleaser = false;
+        // Try to catch the moment when Hal2AidlMapper promotes its wp<StreamHalInterface> to sp<>
+        // in Hal2AidlMapper::resetUnusedPatchesAndPortConfigs and release on our side in order to
+        // make Hal2AidlMapper the sole owner via a temporary sp and enforce destruction of the
+        // stream while the DeviceHalAidl::mLock is held.
+        std::thread releaser([&stream1, &stopReleaser]() {
+            while (!stopReleaser) {
+                if (stream1->getStrongCount() > 1) {
+                    stream1.clear();
+                    break;
+                }
+                std::this_thread::yield();
+            }
+        });
+        sp<StreamOutHalInterface> stream2;
+        // Opening another stream triggers a call to
+        // Hal2AidlMapper::resetUnusedPatchesAndPortConfigs.  It must not cause a deadlock of the
+        // test (main) thread.
+        ASSERT_EQ(OK, mDevice->openOutputStream(43 /*handle*/, AUDIO_DEVICE_OUT_SPEAKER,
+                                                AUDIO_OUTPUT_FLAG_NONE, &config, "" /*address*/,
+                                                &stream2));
+        stopReleaser = true;
+        releaser.join();
+    }
+}
+
 class DeviceHalAidlVendorParametersTest : public testing::Test {
   public:
     void SetUp() override {
@@ -830,9 +988,9 @@
         mVendorExt = ndk::SharedRefBase::make<TestHalAdapterVendorExtension>();
         struct audio_config config = AUDIO_CONFIG_INITIALIZER;
         ::aidl::android::hardware::audio::core::StreamDescriptor descriptor;
+        StreamContextAidl context(descriptor, false /*isAsynchronous*/, 0);
         mStream = sp<StreamHalAidl>::make("test", false /*isInput*/, config, 0 /*nominalLatency*/,
-                                          StreamContextAidl(descriptor, false /*isAsynchronous*/),
-                                          mStreamCommon, mVendorExt);
+                                          std::move(context), mStreamCommon, mVendorExt);
     }
     void TearDown() override {
         mStream.clear();
diff --git a/media/libaudioprocessing/AudioMixerOps.h b/media/libaudioprocessing/AudioMixerOps.h
index ab6a8b6..8f60d29 100644
--- a/media/libaudioprocessing/AudioMixerOps.h
+++ b/media/libaudioprocessing/AudioMixerOps.h
@@ -347,6 +347,7 @@
         [6] = AUDIO_CHANNEL_OUT_5POINT1,
         [7] = AUDIO_CHANNEL_OUT_6POINT1,
         [8] = AUDIO_CHANNEL_OUT_7POINT1,
+        [10] = AUDIO_CHANNEL_OUT_5POINT1POINT4,
         [12] = AUDIO_CHANNEL_OUT_7POINT1POINT4,
         [14] = AUDIO_CHANNEL_OUT_9POINT1POINT4,
         [16] = AUDIO_CHANNEL_OUT_9POINT1POINT6,
diff --git a/media/libaudioprocessing/tests/mixerops_tests.cpp b/media/libaudioprocessing/tests/mixerops_tests.cpp
index 2500ba9..235129f 100644
--- a/media/libaudioprocessing/tests/mixerops_tests.cpp
+++ b/media/libaudioprocessing/tests/mixerops_tests.cpp
@@ -154,6 +154,9 @@
 TEST(mixerops, stereovolume_8) {
     MixerOpsBasicTest<MIXTYPE_MULTI_STEREOVOL, 8>::testStereoVolume();
 }
+TEST(mixerops, stereovolume_10) {
+    MixerOpsBasicTest<MIXTYPE_MULTI_STEREOVOL, 10>::testStereoVolume();
+}
 TEST(mixerops, stereovolume_12) {
     if constexpr (FCC_LIMIT >= 12) { // NOTE: FCC_LIMIT is an enum, so can't #if
         MixerOpsBasicTest<MIXTYPE_MULTI_STEREOVOL, 12>::testStereoVolume();
diff --git a/media/libeffects/downmix/aidl/DownmixContext.cpp b/media/libeffects/downmix/aidl/DownmixContext.cpp
index 593e16f..3a55361 100644
--- a/media/libeffects/downmix/aidl/DownmixContext.cpp
+++ b/media/libeffects/downmix/aidl/DownmixContext.cpp
@@ -100,11 +100,6 @@
     return RetCode::SUCCESS;
 }
 
-void DownmixContext::reset() {
-    disable();
-    resetBuffer();
-}
-
 IEffect::Status DownmixContext::downmixProcess(float* in, float* out, int samples) {
     IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
 
diff --git a/media/libeffects/downmix/aidl/DownmixContext.h b/media/libeffects/downmix/aidl/DownmixContext.h
index a381d7f..1be1508 100644
--- a/media/libeffects/downmix/aidl/DownmixContext.h
+++ b/media/libeffects/downmix/aidl/DownmixContext.h
@@ -32,9 +32,8 @@
   public:
     DownmixContext(int statusDepth, const Parameter::Common& common);
     ~DownmixContext();
-    RetCode enable();
-    RetCode disable();
-    void reset();
+    RetCode enable() override;
+    RetCode disable() override;
 
     RetCode setDmType(Downmix::Type type) {
         mType = type;
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.cpp b/media/libeffects/downmix/aidl/EffectDownmix.cpp
index 883d41d..10c7c4f 100644
--- a/media/libeffects/downmix/aidl/EffectDownmix.cpp
+++ b/media/libeffects/downmix/aidl/EffectDownmix.cpp
@@ -71,26 +71,6 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus DownmixImpl::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->reset();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus DownmixImpl::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::downmix != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.h b/media/libeffects/downmix/aidl/EffectDownmix.h
index b7d621a..cea6d1b 100644
--- a/media/libeffects/downmix/aidl/EffectDownmix.h
+++ b/media/libeffects/downmix/aidl/EffectDownmix.h
@@ -31,7 +31,6 @@
     DownmixImpl() = default;
     ~DownmixImpl() { cleanUp(); }
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
     ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
             REQUIRES(mImplMutex) override;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
index 836e034..8324473 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -244,27 +244,6 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus DynamicsProcessingImpl::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            return ndk::ScopedAStatus::ok();
-        case CommandId::STOP:
-            mContext->disable();
-            return ndk::ScopedAStatus::ok();
-        case CommandId::RESET:
-            mContext->disable();
-            mContext->resetBuffer();
-            return ndk::ScopedAStatus::ok();
-        default:
-            // Need this default handling for vendor extendable CommandId::VENDOR_COMMAND_*
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-}
-
 bool DynamicsProcessingImpl::isParamInRange(const Parameter::Specific& specific) {
     auto& dp = specific.get<Parameter::Specific::dynamicsProcessing>();
     return DynamicsProcessingRanges::isParamInRange(dp, kRanges);
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
index e850ba4..b34cdcf 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -36,7 +36,6 @@
     ndk::ScopedAStatus open(const Parameter::Common& common,
                             const std::optional<Parameter::Specific>& specific,
                             OpenEffectReturn* ret) override;
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
     ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
             REQUIRES(mImplMutex) override;
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
index ada301b..fd4e615 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -48,10 +48,11 @@
     return RetCode::SUCCESS;
 }
 
-void DynamicsProcessingContext::reset() {
+RetCode DynamicsProcessingContext::reset() {
     if (mDpFreq != nullptr) {
-        mDpFreq.reset();
+        mDpFreq->reset();
     }
+    return RetCode::SUCCESS;
 }
 
 RetCode DynamicsProcessingContext::setCommon(const Parameter::Common& common) {
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
index ce657db..15c6811 100644
--- a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -37,9 +37,9 @@
   public:
     DynamicsProcessingContext(int statusDepth, const Parameter::Common& common);
     ~DynamicsProcessingContext() = default;
-    RetCode enable();
-    RetCode disable();
-    void reset();
+    RetCode enable() override;
+    RetCode disable() override;
+    RetCode reset() override;
 
     // override EffectContext::setCommon to update mChannelCount
     RetCode setCommon(const Parameter::Common& common) override;
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
index b803ee4..55e07fb 100644
--- a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
@@ -70,26 +70,6 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus HapticGeneratorImpl::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->reset();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus HapticGeneratorImpl::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
index a775f06..8bae024 100644
--- a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
@@ -30,7 +30,6 @@
     HapticGeneratorImpl() = default;
     ~HapticGeneratorImpl() { cleanUp(); }
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
     ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
             REQUIRES(mImplMutex) override;
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
index 9b2f443..e040fec 100644
--- a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
@@ -71,7 +71,7 @@
     return RetCode::SUCCESS;
 }
 
-void HapticGeneratorContext::reset() {
+RetCode HapticGeneratorContext::reset() {
     for (auto& filter : mProcessorsRecord.filters) {
         filter->clear();
     }
@@ -81,6 +81,7 @@
     for (auto& distortion : mProcessorsRecord.distortions) {
         distortion->clear();
     }
+    return RetCode::SUCCESS;
 }
 
 RetCode HapticGeneratorContext::setHgHapticScales(
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
index 8a736e3..cf38e47 100644
--- a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
@@ -65,9 +65,9 @@
   public:
     HapticGeneratorContext(int statusDepth, const Parameter::Common& common);
     ~HapticGeneratorContext();
-    RetCode enable();
-    RetCode disable();
-    void reset();
+    RetCode enable() override;
+    RetCode disable() override;
+    RetCode reset() override;
 
     RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
     std::vector<HapticGenerator::HapticScale> getHgHapticScales() const;
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
index f89606e..592fd60 100644
--- a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
@@ -70,27 +70,6 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus LoudnessEnhancerImpl::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->disable();
-            mContext->resetBuffer();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus LoudnessEnhancerImpl::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
index 98bdc6b..1e050f3 100644
--- a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
@@ -30,7 +30,6 @@
     LoudnessEnhancerImpl() = default;
     ~LoudnessEnhancerImpl() { cleanUp(); }
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
     ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
             REQUIRES(mImplMutex) override;
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
index d8bcfc0..ac8b14a 100644
--- a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
@@ -43,17 +43,13 @@
     return RetCode::SUCCESS;
 }
 
-void LoudnessEnhancerContext::reset() {
-    float targetAmp = pow(10, mGain / 2000.0f);  // mB to linear amplification
+RetCode LoudnessEnhancerContext::setLeGain(int gainMb) {
+    float targetAmp = pow(10, gainMb / 2000.0f);  // mB to linear amplification
     if (mCompressor != nullptr) {
         // Get samplingRate from input
         mCompressor->Initialize(targetAmp, mCommon.input.base.sampleRate);
     }
-}
-
-RetCode LoudnessEnhancerContext::setLeGain(int gainMb) {
     mGain = gainMb;
-    reset();  // apply parameter update
     return RetCode::SUCCESS;
 }
 
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
index 192b212..67ccd24 100644
--- a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
@@ -34,9 +34,8 @@
     LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common);
     ~LoudnessEnhancerContext() = default;
 
-    RetCode enable();
-    RetCode disable();
-    void reset();
+    RetCode enable() override;
+    RetCode disable() override;
 
     RetCode setLeGain(int gainMb);
     int getLeGain() const { return mGain; }
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
index 044c8dd..e5ab40d 100644
--- a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -35,9 +35,9 @@
     void deInit();
     lvm::BundleEffectType getBundleType() const { return mType; }
 
-    RetCode enable();
+    RetCode enable() override;
     RetCode enableOperatingMode();
-    RetCode disable();
+    RetCode disable() override;
     RetCode disableOperatingMode();
 
     bool isDeviceSupportedBassBoost(
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
index 70c276d..2a81673 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -428,27 +428,6 @@
     return RetCode::SUCCESS;
 }
 
-ndk::ScopedAStatus EffectBundleAidl::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->disable();
-            mContext->resetBuffer();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 // Processing method running in EffectWorker thread.
 IEffect::Status EffectBundleAidl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
     IEffect::Status status = {EX_NULL_POINTER, 0, 0};
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
index 429e941..479579b 100644
--- a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -49,8 +49,6 @@
     IEffect::Status effectProcessImpl(float* in, float* out, int samples)
             REQUIRES(mImplMutex) override;
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
-
     std::string getEffectName() override { return *mEffectName; }
 
   private:
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
index 4d369b1..201c659 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -361,27 +361,6 @@
     return RetCode::SUCCESS;
 }
 
-ndk::ScopedAStatus EffectReverb::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->disable();
-            mContext->resetBuffer();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 // Processing method running in EffectWorker thread.
 IEffect::Status EffectReverb::effectProcessImpl(float* in, float* out, int sampleToProcess) {
     IEffect::Status status = {EX_NULL_POINTER, 0, 0};
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
index e0771a1..4acac1d 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
@@ -42,8 +42,6 @@
     IEffect::Status effectProcessImpl(float* in, float* out, int samples)
             REQUIRES(mImplMutex) override;
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
-
     std::string getEffectName() override { return *mEffectName; }
 
   private:
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
index 44391f2..f55eac5 100644
--- a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -51,8 +51,8 @@
     RetCode init();
     void deInit();
 
-    RetCode enable();
-    RetCode disable();
+    RetCode enable() override;
+    RetCode disable() override;
 
     bool isAuxiliary();
     bool isPreset();
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
index 87d267b..4bc34e7 100644
--- a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
@@ -417,27 +417,6 @@
     return RetCode::SUCCESS;
 }
 
-ndk::ScopedAStatus EffectPreProcessing::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->disable();
-            mContext->resetBuffer();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 // Processing method running in EffectWorker thread.
 IEffect::Status EffectPreProcessing::effectProcessImpl(float* in, float* out, int sampleToProcess) {
     IEffect::Status status = {EX_NULL_POINTER, 0, 0};
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
index 9ce5597..31f5737 100644
--- a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
@@ -43,8 +43,6 @@
     IEffect::Status effectProcessImpl(float* in, float* out, int samples)
             REQUIRES(mImplMutex) override;
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
-
     std::string getEffectName() override { return *mEffectName; }
 
   private:
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.h b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
index 11a2bea..1b9b77b 100644
--- a/media/libeffects/preprocessing/aidl/PreProcessingContext.h
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
@@ -45,8 +45,8 @@
 
     PreProcessingEffectType getPreProcessingType() const { return mType; }
 
-    RetCode enable();
-    RetCode disable();
+    RetCode enable() override;
+    RetCode disable() override;
 
     RetCode setCommon(const Parameter::Common& common) override;
     void updateConfigs(const Parameter::Common& common);
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
index 9b493d4..f4b9b25 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.cpp
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -85,27 +85,6 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus VisualizerImpl::commandImpl(CommandId command) {
-    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
-    switch (command) {
-        case CommandId::START:
-            mContext->enable();
-            break;
-        case CommandId::STOP:
-            mContext->disable();
-            break;
-        case CommandId::RESET:
-            mContext->disable();
-            mContext->resetBuffer();
-            break;
-        default:
-            LOG(ERROR) << __func__ << " commandId " << toString(command) << " not supported";
-            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
-                                                                    "commandIdNotSupported");
-    }
-    return ndk::ScopedAStatus::ok();
-}
-
 ndk::ScopedAStatus VisualizerImpl::setParameterSpecific(const Parameter::Specific& specific) {
     RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
               "EffectNotSupported");
@@ -222,6 +201,7 @@
 RetCode VisualizerImpl::releaseContext() {
     if (mContext) {
         mContext->disable();
+        mContext->reset();
         mContext->resetBuffer();
     }
     return RetCode::SUCCESS;
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
index 3180972..f25b78d 100644
--- a/media/libeffects/visualizer/aidl/Visualizer.h
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -32,7 +32,6 @@
     VisualizerImpl() = default;
     ~VisualizerImpl() { cleanUp(); }
 
-    ndk::ScopedAStatus commandImpl(CommandId command) REQUIRES(mImplMutex) override;
     ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
     ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
             REQUIRES(mImplMutex) override;
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
index 1e08674..a368e52 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -57,7 +57,7 @@
 #endif
     mChannelCount = channelCount;
     mCommon = common;
-    std::fill(mCaptureBuf.begin(), mCaptureBuf.end(), 0x80);
+    reset();
     return RetCode::SUCCESS;
 }
 
@@ -77,8 +77,9 @@
     return RetCode::SUCCESS;
 }
 
-void VisualizerContext::reset() {
+RetCode VisualizerContext::reset() {
     std::fill(mCaptureBuf.begin(), mCaptureBuf.end(), 0x80);
+    return RetCode::SUCCESS;
 }
 
 RetCode VisualizerContext::setCaptureSamples(int samples) {
@@ -109,7 +110,6 @@
     mDownstreamLatency = latency;
     return RetCode::SUCCESS;
 }
-
 int VisualizerContext::getDownstreamLatency() {
     return mDownstreamLatency;
 }
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
index 9715e20..d4abbd3 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.h
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -36,10 +36,10 @@
 
     RetCode initParams(const Parameter::Common& common);
 
-    RetCode enable();
-    RetCode disable();
+    RetCode enable() override;
+    RetCode disable() override;
     // keep all parameters and reset buffer.
-    void reset();
+    RetCode reset() override;
 
     RetCode setCaptureSamples(int32_t captureSize);
     int32_t getCaptureSamples();
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index d4b4b6c..8a962c6 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -255,6 +255,45 @@
 }
 
 cc_library_shared {
+    name: "libmedia_codeclist_capabilities",
+
+    srcs: [
+        "AudioCapabilities.cpp",
+        "CodecCapabilities.cpp",
+        "CodecCapabilitiesUtils.cpp",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
+
+cc_library_shared {
     name: "libmedia_codeclist",
 
     srcs: [
@@ -270,6 +309,7 @@
         "android.hardware.media.omx@1.0",
         "libbinder",
         "liblog",
+        "libmedia_codeclist_capabilities",
         "libstagefright_foundation",
         "libutils",
     ],
diff --git a/media/libmedia/AudioCapabilities.cpp b/media/libmedia/AudioCapabilities.cpp
new file mode 100644
index 0000000..e8cf517
--- /dev/null
+++ b/media/libmedia/AudioCapabilities.cpp
@@ -0,0 +1,394 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioCapabilities"
+
+#include <android-base/strings.h>
+#include <android-base/properties.h>
+
+#include <media/AudioCapabilities.h>
+#include <media/CodecCapabilities.h>
+#include <media/stagefright/MediaCodecConstants.h>
+
+namespace android {
+
+const Range<int>& AudioCapabilities::getBitrateRange() const {
+    return mBitrateRange;
+}
+
+const std::vector<int>& AudioCapabilities::getSupportedSampleRates() const {
+    return mSampleRates;
+}
+
+const std::vector<Range<int>>&
+        AudioCapabilities::getSupportedSampleRateRanges() const {
+    return mSampleRateRanges;
+}
+
+int AudioCapabilities::getMaxInputChannelCount() const {
+    int overallMax = 0;
+    for (int i = mInputChannelRanges.size() - 1; i >= 0; i--) {
+        int lmax = mInputChannelRanges[i].upper();
+        if (lmax > overallMax) {
+            overallMax = lmax;
+        }
+    }
+    return overallMax;
+}
+
+int AudioCapabilities::getMinInputChannelCount() const {
+    int overallMin = MAX_INPUT_CHANNEL_COUNT;
+    for (int i = mInputChannelRanges.size() - 1; i >= 0; i--) {
+        int lmin = mInputChannelRanges[i].lower();
+        if (lmin < overallMin) {
+            overallMin = lmin;
+        }
+    }
+    return overallMin;
+}
+
+const std::vector<Range<int>>&
+        AudioCapabilities::getInputChannelCountRanges() const {
+    return mInputChannelRanges;
+}
+
+// static
+std::shared_ptr<AudioCapabilities> AudioCapabilities::Create(std::string mediaType,
+        std::vector<ProfileLevel> profLevs, const sp<AMessage> &format) {
+    std::shared_ptr<AudioCapabilities> caps(new AudioCapabilities());
+    caps->init(mediaType, profLevs, format);
+    return caps;
+}
+
+void AudioCapabilities::init(std::string mediaType, std::vector<ProfileLevel> profLevs,
+        const sp<AMessage> &format) {
+    mMediaType = mediaType;
+    mProfileLevels = profLevs;
+    mError = 0;
+
+    initWithPlatformLimits();
+    applyLevelLimits();
+    parseFromInfo(format);
+}
+
+void AudioCapabilities::initWithPlatformLimits() {
+    mBitrateRange = Range<int>(0, INT_MAX);
+    mInputChannelRanges.push_back(Range<int>(1, MAX_INPUT_CHANNEL_COUNT));
+
+    const int minSampleRate = base::GetIntProperty("ro.mediacodec.min_sample_rate", 7350);
+    const int maxSampleRate = base::GetIntProperty("ro.mediacodec.max_sample_rate", 192000);
+    mSampleRateRanges.push_back(Range<int>(minSampleRate, maxSampleRate));
+}
+
+bool AudioCapabilities::supports(int sampleRate, int inputChannels) {
+    // channels and sample rates are checked orthogonally
+    if (inputChannels != 0
+            && !std::any_of(mInputChannelRanges.begin(), mInputChannelRanges.end(),
+            [inputChannels](const Range<int> &a) { return a.contains(inputChannels); })) {
+        return false;
+    }
+    if (sampleRate != 0
+            && !std::any_of(mSampleRateRanges.begin(), mSampleRateRanges.end(),
+            [sampleRate](const Range<int> &a) { return a.contains(sampleRate); })) {
+        return false;
+    }
+    return true;
+}
+
+bool AudioCapabilities::isSampleRateSupported(int sampleRate) {
+    return supports(sampleRate, 0);
+}
+
+void AudioCapabilities::limitSampleRates(std::vector<int> rates) {
+    std::vector<Range<int>> sampleRateRanges;
+    std::sort(rates.begin(), rates.end());
+    for (int rate : rates) {
+        if (supports(rate, 0 /* channels */)) {
+            sampleRateRanges.push_back(Range<int>(rate, rate));
+        }
+    }
+    mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, sampleRateRanges);
+    createDiscreteSampleRates();
+}
+
+void AudioCapabilities::createDiscreteSampleRates() {
+    mSampleRates.clear();
+    for (int i = 0; i < mSampleRateRanges.size(); i++) {
+        mSampleRates.push_back(mSampleRateRanges[i].lower());
+    }
+}
+
+void AudioCapabilities::limitSampleRates(std::vector<Range<int>> rateRanges) {
+    sortDistinctRanges(&rateRanges);
+    mSampleRateRanges = intersectSortedDistinctRanges(mSampleRateRanges, rateRanges);
+    // check if all values are discrete
+    for (Range<int> range: mSampleRateRanges) {
+        if (range.lower() != range.upper()) {
+            mSampleRates.clear();
+            return;
+        }
+    }
+    createDiscreteSampleRates();
+}
+
+void AudioCapabilities::applyLevelLimits() {
+    std::vector<int> sampleRates;
+    std::optional<Range<int>> sampleRateRange;
+    std::optional<Range<int>> bitRates;
+    int maxChannels = MAX_INPUT_CHANNEL_COUNT;
+
+    // const char *mediaType = mMediaType.c_str();
+    if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MPEG)) {
+        sampleRates = {
+                8000, 11025, 12000,
+                16000, 22050, 24000,
+                32000, 44100, 48000 };
+        bitRates = Range<int>(8000, 320000);
+        maxChannels = 2;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_NB)) {
+        sampleRates = { 8000 };
+        bitRates = Range<int>(4750, 12200);
+        maxChannels = 1;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AMR_WB)) {
+        sampleRates = { 16000 };
+        bitRates = Range<int>(6600, 23850);
+        maxChannels = 1;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AAC)) {
+        sampleRates = {
+                7350, 8000,
+                11025, 12000, 16000,
+                22050, 24000, 32000,
+                44100, 48000, 64000,
+                88200, 96000 };
+        bitRates = Range<int>(8000, 510000);
+        maxChannels = 48;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_VORBIS)) {
+        bitRates = Range<int>(32000, 500000);
+        sampleRateRange = Range<int>(8000, 192000);
+        maxChannels = 255;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_OPUS)) {
+        bitRates = Range<int>(6000, 510000);
+        sampleRates = { 8000, 12000, 16000, 24000, 48000 };
+        maxChannels = 255;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_RAW)) {
+        sampleRateRange = Range<int>(1, 192000);
+        bitRates = Range<int>(1, 10000000);
+        maxChannels = MAX_NUM_CHANNELS;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_FLAC)) {
+        sampleRateRange = Range<int>(1, 655350);
+        // lossless codec, so bitrate is ignored
+        maxChannels = 255;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_ALAW)
+            || base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_G711_MLAW)) {
+        sampleRates = { 8000 };
+        bitRates = Range<int>(64000, 64000);
+        // platform allows multiple channels for this format
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_MSGSM)) {
+        sampleRates = { 8000 };
+        bitRates = Range<int>(13000, 13000);
+        maxChannels = 1;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AC3)) {
+        maxChannels = 6;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_EAC3)) {
+        maxChannels = 16;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_EAC3_JOC)) {
+        sampleRates = { 48000 };
+        bitRates = Range<int>(32000, 6144000);
+        maxChannels = 16;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_AC4)) {
+        sampleRates = { 44100, 48000, 96000, 192000 };
+        bitRates = Range<int>(16000, 2688000);
+        maxChannels = 24;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS)) {
+        sampleRates = { 44100, 48000 };
+        bitRates = Range<int>(96000, 1524000);
+        maxChannels = 6;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_HD)) {
+        for (ProfileLevel profileLevel: mProfileLevels) {
+            switch (profileLevel.mProfile) {
+                case DTS_HDProfileLBR:
+                    sampleRates = { 22050, 24000, 44100, 48000 };
+                    bitRates = Range<int>(32000, 768000);
+                    break;
+                case DTS_HDProfileHRA:
+                case DTS_HDProfileMA:
+                    sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
+                    bitRates = Range<int>(96000, 24500000);
+                    break;
+                default:
+                    ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile,
+                            mMediaType.c_str());
+                    mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
+                    sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
+                    bitRates = Range<int>(96000, 24500000);
+            }
+        }
+        maxChannels = 8;
+    } else if (base::EqualsIgnoreCase(mMediaType, MIMETYPE_AUDIO_DTS_UHD)) {
+        for (ProfileLevel profileLevel: mProfileLevels) {
+            switch (profileLevel.mProfile) {
+                case DTS_UHDProfileP2:
+                    sampleRates = { 48000 };
+                    bitRates = Range<int>(96000, 768000);
+                    maxChannels = 10;
+                    break;
+                case DTS_UHDProfileP1:
+                    sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
+                    bitRates = Range<int>(96000, 24500000);
+                    maxChannels = 32;
+                    break;
+                default:
+                    ALOGW("Unrecognized profile %d for %s", profileLevel.mProfile,
+                            mMediaType.c_str());
+                    mError |= ERROR_CAPABILITIES_UNRECOGNIZED;
+                    sampleRates = { 44100, 48000, 88200, 96000, 176400, 192000 };
+                    bitRates = Range<int>(96000, 24500000);
+                    maxChannels = 32;
+            }
+        }
+    } else {
+        ALOGW("Unsupported mediaType %s", mMediaType.c_str());
+        mError |= ERROR_CAPABILITIES_UNSUPPORTED;
+    }
+
+    // restrict ranges
+    if (!sampleRates.empty()) {
+        limitSampleRates(sampleRates);
+    } else if (sampleRateRange) {
+        std::vector<Range<int>> rateRanges = { sampleRateRange.value() };
+        limitSampleRates(rateRanges);
+    }
+
+    Range<int> channelRange = Range<int>(1, maxChannels);
+    std::vector<Range<int>> inputChannels = { channelRange };
+    applyLimits(inputChannels, bitRates);
+}
+
+void AudioCapabilities::applyLimits(
+        const std::vector<Range<int>> &inputChannels,
+        const std::optional<Range<int>> &bitRates) {
+    // clamp & make a local copy
+    std::vector<Range<int>> inputChannelsCopy(inputChannels.size());
+    for (int i = 0; i < inputChannels.size(); i++) {
+        int lower = inputChannels[i].clamp(1);
+        int upper = inputChannels[i].clamp(MAX_INPUT_CHANNEL_COUNT);
+        inputChannelsCopy[i] = Range<int>(lower, upper);
+    }
+
+    // sort, intersect with existing, & save channel list
+    sortDistinctRanges(&inputChannelsCopy);
+    mInputChannelRanges = intersectSortedDistinctRanges(inputChannelsCopy, mInputChannelRanges);
+
+    if (bitRates) {
+        mBitrateRange = mBitrateRange.intersect(bitRates.value());
+    }
+}
+
+void AudioCapabilities::parseFromInfo(const sp<AMessage> &format) {
+    int maxInputChannels = MAX_INPUT_CHANNEL_COUNT;
+    std::vector<Range<int>> channels = { Range<int>(1, maxInputChannels) };
+    std::optional<Range<int>> bitRates = POSITIVE_INTEGERS;
+
+    AString rateAString;
+    if (format->findString("sample-rate-ranges", &rateAString)) {
+        std::vector<std::string> rateStrings = base::Split(std::string(rateAString.c_str()), ",");
+        std::vector<Range<int>> rateRanges;
+        for (std::string rateString : rateStrings) {
+            std::optional<Range<int>> rateRange = ParseIntRange(rateString);
+            if (!rateRange) {
+                continue;
+            }
+            rateRanges.push_back(rateRange.value());
+        }
+        limitSampleRates(rateRanges);
+    }
+
+    // we will prefer channel-ranges over max-channel-count
+    AString valueStr;
+    if (format->findString("channel-ranges", &valueStr)) {
+        std::vector<std::string> channelStrings = base::Split(std::string(valueStr.c_str()), ",");
+        std::vector<Range<int>> channelRanges;
+        for (std::string channelString : channelStrings) {
+            std::optional<Range<int>> channelRange = ParseIntRange(channelString);
+            if (!channelRange) {
+                continue;
+            }
+            channelRanges.push_back(channelRange.value());
+        }
+        channels = channelRanges;
+    } else if (format->findString("channel-range", &valueStr)) {
+        std::optional<Range<int>> oneRange = ParseIntRange(std::string(valueStr.c_str()));
+        if (oneRange) {
+            channels = { oneRange.value() };
+        }
+    } else if (format->findString("max-channel-count", &valueStr)) {
+        maxInputChannels = std::atoi(valueStr.c_str());
+        if (maxInputChannels == 0) {
+            channels = { Range<int>(0, 0) };
+        } else {
+            channels = { Range<int>(1, maxInputChannels) };
+        }
+    } else if ((mError & ERROR_CAPABILITIES_UNSUPPORTED) != 0) {
+        maxInputChannels = 0;
+        channels = { Range<int>(0, 0) };
+    }
+
+    if (format->findString("bitrate-range", &valueStr)) {
+        std::optional<Range<int>> parsedBitrate = ParseIntRange(valueStr.c_str());
+        if (parsedBitrate) {
+            bitRates = bitRates.value().intersect(parsedBitrate.value());
+        }
+    }
+
+    applyLimits(channels, bitRates);
+}
+
+void AudioCapabilities::getDefaultFormat(sp<AMessage> &format) {
+    // report settings that have only a single choice
+    if (mBitrateRange.lower() == mBitrateRange.upper()) {
+        format->setInt32(KEY_BIT_RATE, mBitrateRange.lower());
+    }
+    if (getMaxInputChannelCount() == 1) {
+        // mono-only format
+        format->setInt32(KEY_CHANNEL_COUNT, 1);
+    }
+    if (!mSampleRates.empty() && mSampleRates.size() == 1) {
+        format->setInt32(KEY_SAMPLE_RATE, mSampleRates[0]);
+    }
+}
+
+bool AudioCapabilities::supportsFormat(const sp<AMessage> &format) {
+    int32_t sampleRate;
+    format->findInt32(KEY_SAMPLE_RATE, &sampleRate);
+    int32_t channels;
+    format->findInt32(KEY_CHANNEL_COUNT, &channels);
+
+    if (!supports(sampleRate, channels)) {
+        return false;
+    }
+
+    if (!CodecCapabilities::SupportsBitrate(mBitrateRange, format)) {
+        return false;
+    }
+
+    // nothing to do for:
+    // KEY_CHANNEL_MASK: codecs don't get this
+    // KEY_IS_ADTS:      required feature for all AAC decoders
+    return true;
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/media/libmedia/CodecCapabilities.cpp b/media/libmedia/CodecCapabilities.cpp
new file mode 100644
index 0000000..5bed1c4
--- /dev/null
+++ b/media/libmedia/CodecCapabilities.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecCapabilities"
+
+#include <utils/Log.h>
+#include <media/CodecCapabilities.h>
+#include <media/CodecCapabilitiesUtils.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+namespace android {
+
+bool CodecCapabilities::SupportsBitrate(Range<int> bitrateRange,
+        const sp<AMessage> &format) {
+    // consider max bitrate over average bitrate for support
+    int32_t maxBitrate = 0;
+    format->findInt32(KEY_MAX_BIT_RATE, &maxBitrate);
+    int32_t bitrate = 0;
+    format->findInt32(KEY_BIT_RATE, &bitrate);
+
+    if (bitrate == 0) {
+        bitrate = maxBitrate;
+    } else if (maxBitrate != 0) {
+        bitrate = std::max(bitrate, maxBitrate);
+    }
+
+    if (bitrate > 0) {
+        return bitrateRange.contains(bitrate);
+    }
+
+    return true;
+}
+
+const std::string& CodecCapabilities::getMediaType() {
+    return mMediaType;
+}
+
+const std::vector<ProfileLevel>& CodecCapabilities::getProfileLevels() {
+    return mProfileLevels;
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/media/libmedia/CodecCapabilitiesUtils.cpp b/media/libmedia/CodecCapabilitiesUtils.cpp
new file mode 100644
index 0000000..edfc9be
--- /dev/null
+++ b/media/libmedia/CodecCapabilitiesUtils.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecCapabilitiesUtils"
+#include <utils/Log.h>
+
+#include <algorithm>
+#include <cmath>
+#include <regex>
+#include <string>
+#include <vector>
+
+#include <media/CodecCapabilitiesUtils.h>
+
+#include <media/stagefright/foundation/AUtils.h>
+
+namespace android {
+
+std::optional<Range<int>> ParseIntRange(const std::string &str) {
+    if (str.empty()) {
+        ALOGW("could not parse empty integer range");
+        return std::nullopt;
+    }
+    int lower, upper;
+    std::regex regex("([0-9]+)-([0-9]+)");
+    std::smatch match;
+    if (std::regex_match(str, match, regex)) {
+        lower = std::atoi(match[1].str().c_str());
+        upper = std::atoi(match[2].str().c_str());
+    } else if (std::atoi(str.c_str()) != 0) {
+        lower = upper = std::atoi(str.c_str());
+    } else {
+        ALOGW("could not parse integer range: %s", str.c_str());
+        return std::nullopt;
+    }
+    return std::make_optional<Range<int>>(lower, upper);
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/media/libmedia/include/media/AudioCapabilities.h b/media/libmedia/include/media/AudioCapabilities.h
new file mode 100644
index 0000000..2bc3335
--- /dev/null
+++ b/media/libmedia/include/media/AudioCapabilities.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AUDIO_CAPABILITIES_H_
+
+#define AUDIO_CAPABILITIES_H_
+
+#include <media/CodecCapabilitiesUtils.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <system/audio.h>
+
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct AudioCapabilities {
+    /**
+     * Create AudioCapabilities.
+     */
+    static std::shared_ptr<AudioCapabilities> Create(std::string mediaType,
+            std::vector<ProfileLevel> profLevs, const sp<AMessage> &format);
+
+    /**
+     * Returns the range of supported bitrates in bits/second.
+     */
+    const Range<int>& getBitrateRange() const;
+
+    /**
+     * Returns the array of supported sample rates if the codec
+     * supports only discrete values. Otherwise, it returns an empty array.
+     * The array is sorted in ascending order.
+     */
+    const std::vector<int>& getSupportedSampleRates() const;
+
+    /**
+     * Returns the array of supported sample rate ranges.  The
+     * array is sorted in ascending order, and the ranges are
+     * distinct.
+     */
+    const std::vector<Range<int>>& getSupportedSampleRateRanges() const;
+
+    /**
+     * Returns the maximum number of input channels supported.
+     * The returned value should be between 1 and 255.
+     *
+     * Through {@link android.os.Build.VERSION_CODES#R}, this method indicated support
+     * for any number of input channels between 1 and this maximum value.
+     *
+     * As of {@link android.os.Build.VERSION_CODES#S},
+     * the implied lower limit of 1 channel is no longer valid.
+     * As of {@link android.os.Build.VERSION_CODES#S}, {@link #getMaxInputChannelCount} is
+     * superseded by {@link #getInputChannelCountRanges},
+     * which returns an array of ranges of channels.
+     * The {@link #getMaxInputChannelCount} method will return the highest value
+     * in the ranges returned by {@link #getInputChannelCountRanges}
+     */
+    int getMaxInputChannelCount() const;
+
+    /**
+     * Returns the minimum number of input channels supported.
+     * This is often 1, but does vary for certain mime types.
+     *
+     * This returns the lowest channel count in the ranges returned by
+     * {@link #getInputChannelCountRanges}.
+     */
+    int getMinInputChannelCount() const;
+
+    /**
+     * Returns an array of ranges representing the number of input channels supported.
+     * The codec supports any number of input channels within this range.
+     *
+     * This supersedes the {@link #getMaxInputChannelCount} method.
+     *
+     * For many codecs, this will be a single range [1..N], for some N.
+     *
+     * The returned array cannot be empty.
+     */
+    const std::vector<Range<int>>& getInputChannelCountRanges() const;
+
+    /**
+     * Query whether the sample rate is supported by the codec.
+     */
+    bool isSampleRateSupported(int sampleRate);
+
+    /* For internal use only. Not exposed as a public API */
+    void getDefaultFormat(sp<AMessage> &format);
+
+    /* For internal use only. Not exposed as a public API */
+    bool supportsFormat(const sp<AMessage> &format);
+
+private:
+    static constexpr int MAX_INPUT_CHANNEL_COUNT = 30;
+    static constexpr uint32_t MAX_NUM_CHANNELS = FCC_LIMIT;
+
+    int mError;
+    std::string mMediaType;
+    std::vector<ProfileLevel> mProfileLevels;
+
+    Range<int> mBitrateRange;
+
+    std::vector<int> mSampleRates;
+    std::vector<Range<int>> mSampleRateRanges;
+    std::vector<Range<int>> mInputChannelRanges;
+
+    /* no public constructor */
+    AudioCapabilities() {}
+    void init(std::string mediaType, std::vector<ProfileLevel> profLevs,
+            const sp<AMessage> &format);
+    void initWithPlatformLimits();
+    bool supports(int sampleRate, int inputChannels);
+    void limitSampleRates(std::vector<int> rates);
+    void createDiscreteSampleRates();
+    void limitSampleRates(std::vector<Range<int>> rateRanges);
+    void applyLevelLimits();
+    void applyLimits(const std::vector<Range<int>> &inputChannels,
+            const std::optional<Range<int>> &bitRates);
+    void parseFromInfo(const sp<AMessage> &format);
+
+    friend struct CodecCapabilities;
+};
+
+}  // namespace android
+
+#endif // AUDIO_CAPABILITIES_H_
\ No newline at end of file
diff --git a/media/libmedia/include/media/CodecCapabilities.h b/media/libmedia/include/media/CodecCapabilities.h
new file mode 100644
index 0000000..9d1c4ea
--- /dev/null
+++ b/media/libmedia/include/media/CodecCapabilities.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2024, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC_CAPABILITIES_H_
+
+#define CODEC_CAPABILITIES_H_
+
+#include <media/AudioCapabilities.h>
+#include <media/CodecCapabilitiesUtils.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/MediaCodecConstants.h>
+
+#include <utils/Errors.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+struct CodecCapabilities {
+
+    static bool SupportsBitrate(Range<int> bitrateRange,
+            const sp<AMessage> &format);
+
+    /**
+     * Returns the media type for which this codec-capability object was created.
+     */
+    const std::string& getMediaType();
+
+    /**
+     * Returns the supported profile levels.
+     */
+    const std::vector<ProfileLevel>& getProfileLevels();
+
+private:
+    std::string mMediaType;
+    std::vector<ProfileLevel> mProfileLevels;
+
+    std::shared_ptr<AudioCapabilities> mAudioCaps;
+};
+
+}  // namespace android
+
+#endif // CODEC_CAPABILITIES_H_
\ No newline at end of file
diff --git a/media/libmedia/include/media/CodecCapabilitiesUtils.h b/media/libmedia/include/media/CodecCapabilitiesUtils.h
new file mode 100644
index 0000000..2bf822a
--- /dev/null
+++ b/media/libmedia/include/media/CodecCapabilitiesUtils.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CODEC_CAPABILITIES__UTILS_H_
+
+#define CODEC_CAPABILITIES__UTILS_H_
+
+#include <algorithm>
+#include <cmath>
+#include <optional>
+#include <string>
+#include <vector>
+
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AUtils.h>
+
+namespace android {
+
+struct ProfileLevel {
+    uint32_t mProfile;
+    uint32_t mLevel;
+    bool operator <(const ProfileLevel &o) const {
+        return mProfile < o.mProfile || (mProfile == o.mProfile && mLevel < o.mLevel);
+    }
+};
+
+/**
+ * Immutable class for describing the range of two numeric values.
+ *
+ * To make it immutable, all data are private and all functions are const.
+ *
+ * From frameworks/base/core/java/android/util/Range.java
+ */
+template<typename T>
+struct Range {
+    Range() : lower_(), upper_() {}
+
+    Range(T l, T u) : lower_(l), upper_(u) {}
+
+    constexpr bool empty() const { return lower_ > upper_; }
+
+    T lower() const { return lower_; }
+
+    T upper() const { return upper_; }
+
+    // Check if a value is in the range.
+    bool contains(T value) const {
+        return lower_ <= value && upper_ >= value;
+    }
+
+    bool contains(Range<T> range) const {
+        return (range.lower_ >= lower_) && (range.upper_ <= upper_);
+    }
+
+    // Clamp a value in the range
+    T clamp(T value) const{
+        if (value < lower_) {
+            return lower_;
+        } else if (value > upper_) {
+            return upper_;
+        } else {
+            return value;
+        }
+    }
+
+    // Return the intersected range
+    Range<T> intersect(Range<T> range) const {
+        if (lower_ >= range.lower() && range.upper() >= upper_) {
+            // range includes this
+            return *this;
+        } else if (range.lower() >= lower_ && range.upper() <= upper_) {
+            // this includes range
+            return range;
+        } else {
+            // if ranges are disjoint returns an empty Range(lower > upper)
+            Range<T> result = Range<T>(std::max(lower_, range.lower_),
+                    std::min(upper_, range.upper_));
+            if (result.empty()) {
+                ALOGE("Failed to intersect 2 ranges as they are disjoint");
+            }
+            return result;
+        }
+    }
+
+    /**
+     * Returns the intersection of this range and the inclusive range
+     * specified by {@code [lower, upper]}.
+     * <p>
+     * See {@link #intersect(Range)} for more details.</p>
+     *
+     * @param lower a non-{@code null} {@code T} reference
+     * @param upper a non-{@code null} {@code T} reference
+     * @return the intersection of this range and the other range
+     *
+     * @throws NullPointerException if {@code lower} or {@code upper} was {@code null}
+     * @throws IllegalArgumentException if the ranges are disjoint.
+     */
+    Range<T> intersect(T lower, T upper) {
+        return Range(std::max(lower_, lower), std::min(upper_, upper));
+    }
+
+private:
+    T lower_;
+    T upper_;
+};
+
+static const Range<int> POSITIVE_INTEGERS = Range<int>(1, INT_MAX);
+
+// found stuff that is not supported by framework (=> this should not happen)
+constexpr int ERROR_CAPABILITIES_UNRECOGNIZED   = (1 << 0);
+// found profile/level for which we don't have capability estimates
+constexpr int ERROR_CAPABILITIES_UNSUPPORTED    = (1 << 1);
+// have not found any profile/level for which we don't have capability estimate
+// constexpr int ERROR_NONE_SUPPORTED = (1 << 2);
+
+/**
+ * Sorts distinct (non-intersecting) range array in ascending order.
+ * From frameworks/base/media/java/android/media/Utils.java
+ */
+template<typename T>
+void sortDistinctRanges(std::vector<Range<T>> *ranges) {
+    std::sort(ranges->begin(), ranges->end(),
+            [](Range<T> r1, Range<T> r2) {
+        if (r1.upper() < r2.lower()) {
+            return true;
+        } else if (r1.lower() > r2.upper()) {
+            return false;
+        } else {
+            ALOGE("sample rate ranges must be distinct.");
+            return false;
+        }
+    });
+}
+
+/**
+ * Returns the intersection of two sets of non-intersecting ranges
+ * From frameworks/base/media/java/android/media/Utils.java
+ * @param one a sorted set of non-intersecting ranges in ascending order
+ * @param another another sorted set of non-intersecting ranges in ascending order
+ * @return the intersection of the two sets, sorted in ascending order
+ */
+template<typename T>
+std::vector<Range<T>> intersectSortedDistinctRanges(
+        const std::vector<Range<T>> &one, const std::vector<Range<T>> &another) {
+    std::vector<Range<T>> result;
+    int ix = 0;
+    for (Range<T> range : another) {
+        while (ix < one.size() && one[ix].upper() < range.lower()) {
+            ++ix;
+        }
+        while (ix < one.size() && one[ix].upper() < range.upper()) {
+            result.push_back(range.intersect(one[ix]));
+            ++ix;
+        }
+        if (ix == one.size()) {
+            break;
+        }
+        if (one[ix].lower() <= range.upper()) {
+            result.push_back(range.intersect(one[ix]));
+        }
+    }
+    return result;
+}
+
+// parse string into int range
+std::optional<Range<int>> ParseIntRange(const std::string &str);
+
+}  // namespace android
+
+#endif  // CODEC_CAPABILITIES__UTILS_H_
\ No newline at end of file
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index 88a2dc4..72aca98 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -20,6 +20,8 @@
 
 #include <android-base/macros.h>
 #include <binder/Parcel.h>
+#include <media/CodecCapabilities.h>
+#include <media/CodecCapabilitiesUtils.h>
 #include <media/stagefright/foundation/ABase.h>
 #include <media/stagefright/foundation/AString.h>
 
@@ -43,13 +45,10 @@
 struct MediaCodecListWriter;
 
 struct MediaCodecInfo : public RefBase {
-    struct ProfileLevel {
-        uint32_t mProfile;
-        uint32_t mLevel;
-        bool operator <(const ProfileLevel &o) const {
-            return mProfile < o.mProfile || (mProfile == o.mProfile && mLevel < o.mLevel);
-        }
-    };
+
+    // Moved to CodecCapabilitiesUtils.h
+    // Map MediaCodecInfo::ProfileLevel to android::ProfileLevel to maintain compatibility.
+    typedef ::android::ProfileLevel ProfileLevel;
 
     struct CapabilitiesWriter;
 
diff --git a/media/libmedia/include/media/RingBuffer.h b/media/libmedia/include/media/RingBuffer.h
index 4d92d87..a08f35e 100644
--- a/media/libmedia/include/media/RingBuffer.h
+++ b/media/libmedia/include/media/RingBuffer.h
@@ -44,8 +44,14 @@
     /**
      * Forward iterator to this class.  Implements an std:forward_iterator.
      */
-    class iterator : public std::iterator<std::forward_iterator_tag, T> {
+    class iterator {
     public:
+        using iterator_category = std::forward_iterator_tag;
+        using value_type = T;
+        using difference_type = std::ptrdiff_t;
+        using pointer = T*;
+        using reference = T&;
+
         iterator(T* ptr, size_t size, size_t pos, size_t ctr);
 
         iterator& operator++();
@@ -357,5 +363,3 @@
 }; // namespace android
 
 #endif // ANDROID_SERVICE_UTILS_RING_BUFFER_H
-
-
diff --git a/media/libmedia/tests/codeccapabilities/Android.bp b/media/libmedia/tests/codeccapabilities/Android.bp
new file mode 100644
index 0000000..79eb71a
--- /dev/null
+++ b/media/libmedia/tests/codeccapabilities/Android.bp
@@ -0,0 +1,36 @@
+cc_test {
+    name: "CodecCapabilitiesTest",
+    team: "trendy_team_media_codec_framework",
+
+    test_suites: [
+        "general-tests",
+    ],
+    gtest: true,
+
+    srcs: [
+        "CodecCapabilitiesTest.cpp",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libmedia_codeclist", // available >= R
+        "libmedia_codeclist_capabilities",
+        "libstagefright",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+
+    sanitize: {
+        cfi: true,
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
diff --git a/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp b/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp
new file mode 100644
index 0000000..89c9739
--- /dev/null
+++ b/media/libmedia/tests/codeccapabilities/CodecCapabilitiesTest.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "CodecCapabilitiesTest"
+
+#include <utils/Log.h>
+
+#include <memory>
+
+#include <gtest/gtest.h>
+
+#include <binder/Parcel.h>
+
+#include <media/CodecCapabilities.h>
+#include <media/CodecCapabilitiesUtils.h>
+#include <media/MediaCodecInfo.h>
+
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/MediaCodecList.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AString.h>
+
+using namespace android;
+
+class AudioCapsAacTest : public testing::Test {
+protected:
+    AudioCapsAacTest() {
+        std::string mediaType = MIMETYPE_AUDIO_AAC;
+
+        sp<AMessage> details = new AMessage;
+        details->setString("bitrate-range", "8000-960000");
+        details->setString("max-channel-count", "8");
+        details->setString("sample-rate-ranges",
+                "7350,8000,11025,12000,16000,22050,24000,32000,44100,48000");
+
+        std::vector<ProfileLevel> profileLevel{
+            ProfileLevel(2, 0),
+            ProfileLevel(5, 0),
+            ProfileLevel(29, 0),
+            ProfileLevel(23, 0),
+            ProfileLevel(39, 0),
+            ProfileLevel(20, 0),
+            ProfileLevel(42, 0),
+        };
+
+        audioCaps = AudioCapabilities::Create(mediaType, profileLevel, details);
+    }
+
+    std::shared_ptr<AudioCapabilities> audioCaps;
+};
+
+TEST_F(AudioCapsAacTest, AudioCaps_Aac_Bitrate) {
+    const Range<int>& bitrateRange = audioCaps->getBitrateRange();
+    EXPECT_EQ(bitrateRange.lower(), 8000) << "bitrate range1 does not match. lower: "
+            << bitrateRange.lower();
+    EXPECT_EQ(bitrateRange.upper(), 510000) << "bitrate range1 does not match. upper: "
+            << bitrateRange.upper();
+}
+
+TEST_F(AudioCapsAacTest, AudioCaps_Aac_InputChannelCount) {
+    int maxInputChannelCount = audioCaps->getMaxInputChannelCount();
+    EXPECT_EQ(maxInputChannelCount, 8);
+    int minInputChannelCount = audioCaps->getMinInputChannelCount();
+    EXPECT_EQ(minInputChannelCount, 1);
+}
+
+TEST_F(AudioCapsAacTest, AudioCaps_Aac_SupportedSampleRates) {
+    const std::vector<int>& sampleRates = audioCaps->getSupportedSampleRates();
+    EXPECT_EQ(sampleRates, std::vector<int>({7350, 8000, 11025, 12000, 16000, 22050,
+            24000, 32000, 44100, 48000}));
+
+    EXPECT_FALSE(audioCaps->isSampleRateSupported(6000))
+            << "isSampleRateSupported returned true for unsupported sample rate";
+    EXPECT_TRUE(audioCaps->isSampleRateSupported(8000))
+            << "isSampleRateSupported returned false for supported sample rate";
+    EXPECT_TRUE(audioCaps->isSampleRateSupported(12000))
+            << "isSampleRateSupported returned false for supported sample rate";
+    EXPECT_FALSE(audioCaps->isSampleRateSupported(44000))
+            << "isSampleRateSupported returned true for unsupported sample rate";
+    EXPECT_TRUE(audioCaps->isSampleRateSupported(48000))
+            << "isSampleRateSupported returned true for unsupported sample rate";
+}
+
+class AudioCapsRawTest : public testing::Test {
+protected:
+    AudioCapsRawTest() {
+        std::string mediaType = MIMETYPE_AUDIO_RAW;
+
+        sp<AMessage> details = new AMessage;
+        details->setString("bitrate-range", "1-10000000");
+        details->setString("channel-ranges", "1,2,3,4,5,6,7,8,9,10,11,12");
+        details->setString("sample-rate-ranges", "8000-192000");
+
+        std::vector<ProfileLevel> profileLevel;
+
+        audioCaps = AudioCapabilities::Create(mediaType, profileLevel, details);
+    }
+
+    std::shared_ptr<AudioCapabilities> audioCaps;
+};
+
+TEST_F(AudioCapsRawTest, AudioCaps_Raw_Bitrate) {
+    const Range<int>& bitrateRange = audioCaps->getBitrateRange();
+    EXPECT_EQ(bitrateRange.lower(), 1);
+    EXPECT_EQ(bitrateRange.upper(), 10000000);
+}
+
+TEST_F(AudioCapsRawTest, AudioCaps_Raw_InputChannelCount) {
+    int maxInputChannelCount = audioCaps->getMaxInputChannelCount();
+    EXPECT_EQ(maxInputChannelCount, 12);
+    int minInputChannelCount = audioCaps->getMinInputChannelCount();
+    EXPECT_EQ(minInputChannelCount, 1);
+}
+
+TEST_F(AudioCapsRawTest, AudioCaps_Raw_InputChannelCountRanges) {
+    const std::vector<Range<int>>& inputChannelCountRanges
+            = audioCaps->getInputChannelCountRanges();
+    std::vector<Range<int>> expectedOutput({{1,1}, {2,2}, {3,3}, {4,4}, {5,5},
+            {6,6}, {7,7}, {8,8}, {9,9}, {10,10}, {11,11}, {12,12}});
+    ASSERT_EQ(inputChannelCountRanges.size(), expectedOutput.size());
+    for (int i = 0; i < inputChannelCountRanges.size(); i++) {
+        EXPECT_EQ(inputChannelCountRanges.at(i).lower(), expectedOutput.at(i).lower());
+        EXPECT_EQ(inputChannelCountRanges.at(i).upper(), expectedOutput.at(i).upper());
+    }
+}
+
+TEST_F(AudioCapsRawTest, AudioCaps_Raw_SupportedSampleRates) {
+    const std::vector<Range<int>>& sampleRateRanges = audioCaps->getSupportedSampleRateRanges();
+    EXPECT_EQ(sampleRateRanges.size(), 1);
+    EXPECT_EQ(sampleRateRanges.at(0).lower(), 8000);
+    EXPECT_EQ(sampleRateRanges.at(0).upper(), 192000);
+
+    EXPECT_EQ(audioCaps->isSampleRateSupported(7000), false);
+    EXPECT_EQ(audioCaps->isSampleRateSupported(10000), true);
+    EXPECT_EQ(audioCaps->isSampleRateSupported(193000), false);
+}
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 718f782..a10c509 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -45,6 +45,7 @@
         "android.hardware.media.omx@1.0",
         "av-types-aidl-cpp",
         "framework-permission-aidl-cpp",
+        "libaconfig_storage_read_api_cc",
         "libaudioclient_aidl_conversion",
         "libbase",
         "libbinder_ndk",
@@ -76,6 +77,7 @@
         "libstagefright_httplive",
         "libutils",
         "packagemanager_aidl-cpp",
+        "server_configurable_flags",
     ],
 
     header_libs: [
@@ -86,6 +88,7 @@
     ],
 
     static_libs: [
+        "com.android.media.flags.editing-aconfig-cc",
         "libplayerservice_datasource",
         "libstagefright_nuplayer",
         "libstagefright_rtsp",
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index dce6ba8..086baa3 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -68,6 +68,7 @@
 #include <system/audio.h>
 
 #include <media/stagefright/rtsp/ARTPWriter.h>
+#include <com_android_media_editing_flags.h>
 
 namespace android {
 
@@ -2121,7 +2122,8 @@
         uint32_t bLayers = std::min(2u, tsLayers - 1); // use up-to 2 B-layers
         // TODO(b/341121900): Remove this once B frames are handled correctly in screen recorder
         // use case in case of mic only
-        if (mAudioSource == AUDIO_SOURCE_MIC && mVideoSource == VIDEO_SOURCE_SURFACE) {
+        if (!com::android::media::editing::flags::stagefrightrecorder_enable_b_frames()
+                && mAudioSource == AUDIO_SOURCE_MIC && mVideoSource == VIDEO_SOURCE_SURFACE) {
             bLayers = 0;
         }
         uint32_t pLayers = tsLayers - bLayers;
diff --git a/media/libmediaplayerservice/fuzzer/Android.bp b/media/libmediaplayerservice/fuzzer/Android.bp
index 78163e4..fcdaff9 100644
--- a/media/libmediaplayerservice/fuzzer/Android.bp
+++ b/media/libmediaplayerservice/fuzzer/Android.bp
@@ -64,6 +64,7 @@
         "mediarecorder_fuzzer.cpp",
     ],
     defaults: [
+        "libaudioflinger_dependencies",
         "libmediaplayerserviceFuzzer_defaults",
     ],
     static_libs: [
@@ -76,12 +77,10 @@
     ],
     shared_libs: [
         "android.hardware.media.omx@1.0",
-        "av-types-aidl-cpp",
         "media_permission-aidl-cpp",
-        "libaudioclient_aidl_conversion",
         "libactivitymanager_aidl",
         "libandroid_net",
-        "libaudioclient",
+        "libaudioflinger",
         "libcamera_client",
         "libcodec2_client",
         "libcrypto",
@@ -89,24 +88,13 @@
         "libdrmframework",
         "libgui",
         "libhidlbase",
-        "liblog",
         "libmedia_codeclist",
         "libmedia_omx",
         "libmediadrm",
-        "libmediametrics",
-        "libmediautils",
-        "libmemunreachable",
         "libnetd_client",
-        "libpowermanager",
         "libstagefright_httplive",
         "packagemanager_aidl-cpp",
         "libfakeservicemanager",
-        "libvibrator",
-        "libnbaio",
-        "libnblog",
-        "libpowermanager",
-        "libaudioprocessing",
-        "libaudioflinger",
         "libresourcemanagerservice",
         "libmediametricsservice",
         "mediametricsservice-aidl-cpp",
@@ -122,10 +110,6 @@
         "android.hardware.camera.device@3.4",
         "libaudiohal@7.0",
     ],
-    header_libs: [
-        "libaudiohal_headers",
-        "libaudioflinger_headers",
-    ],
 }
 
 cc_fuzz {
diff --git a/media/libmediaplayerservice/fuzzer/corpus/seed-2024-08-29-0 b/media/libmediaplayerservice/fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..aae78ae
--- /dev/null
+++ b/media/libmediaplayerservice/fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index ac178aa..d084f10 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -321,6 +321,7 @@
 
     static_libs: [
         "android.media.codec-aconfig-cc",
+        "com.android.media.flags.editing-aconfig-cc",
         "libstagefright_esds",
         "libstagefright_color_conversion",
         "libyuv",
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 46703bb..cc78510 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -18,19 +18,14 @@
 #define LOG_TAG "FrameDecoder"
 #define ATRACE_TAG  ATRACE_TAG_VIDEO
 #include "include/FrameDecoder.h"
-#include "include/FrameCaptureLayer.h"
-#include "include/HevcUtils.h"
+#include <android_media_codec.h>
 #include <binder/MemoryBase.h>
 #include <binder/MemoryHeapBase.h>
 #include <gui/Surface.h>
 #include <inttypes.h>
-#include <mediadrm/ICrypto.h>
 #include <media/IMediaSource.h>
 #include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/avc_utils.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/ColorUtils.h>
+#include <media/stagefright/CodecBase.h>
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/FrameCaptureProcessor.h>
 #include <media/stagefright/MediaBuffer.h>
@@ -39,13 +34,24 @@
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/Utils.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/ColorUtils.h>
+#include <media/stagefright/foundation/avc_utils.h>
+#include <mediadrm/ICrypto.h>
 #include <private/media/VideoFrame.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include "include/FrameCaptureLayer.h"
+#include "include/HevcUtils.h"
+
+#include <C2Buffer.h>
+#include <Codec2BufferUtils.h>
 
 namespace android {
 
 static const int64_t kBufferTimeOutUs = 10000LL; // 10 msec
+static const int64_t kAsyncBufferTimeOutUs = 2000000LL; // 2000 msec
 static const size_t kRetryCount = 100; // must be >0
 static const int64_t kDefaultSampleDurationUs = 33333LL; // 33ms
 // For codec, 0 is the highest importance; higher the number lesser important.
@@ -232,6 +238,104 @@
     return false;
 }
 
+AsyncCodecHandler::AsyncCodecHandler(const wp<FrameDecoder>& frameDecoder) {
+    mFrameDecoder = frameDecoder;
+}
+
+void AsyncCodecHandler::onMessageReceived(const sp<AMessage>& msg) {
+    switch (msg->what()) {
+        case FrameDecoder::kWhatCallbackNotify:
+            int32_t callbackId;
+            if (!msg->findInt32("callbackID", &callbackId)) {
+                ALOGE("kWhatCallbackNotify: callbackID is expected.");
+                break;
+            }
+            switch (callbackId) {
+                case MediaCodec::CB_INPUT_AVAILABLE: {
+                    int32_t index;
+                    if (!msg->findInt32("index", &index)) {
+                        ALOGE("CB_INPUT_AVAILABLE: index is expected.");
+                        break;
+                    }
+                    ALOGD("CB_INPUT_AVAILABLE received, index is %d", index);
+                    sp<FrameDecoder> frameDecoder = mFrameDecoder.promote();
+                    if (frameDecoder != nullptr) {
+                        frameDecoder->handleInputBufferAsync(index);
+                    }
+                    break;
+                }
+                case MediaCodec::CB_OUTPUT_AVAILABLE: {
+                    int32_t index;
+                    int64_t timeUs;
+                    CHECK(msg->findInt32("index", &index));
+                    CHECK(msg->findInt64("timeUs", &timeUs));
+                    ALOGD("CB_OUTPUT_AVAILABLE received, index is %d", index);
+                    sp<FrameDecoder> frameDecoder = mFrameDecoder.promote();
+                    if (frameDecoder != nullptr) {
+                        frameDecoder->handleOutputBufferAsync(index, timeUs);
+                    }
+                    break;
+                }
+                case MediaCodec::CB_OUTPUT_FORMAT_CHANGED: {
+                    ALOGD("CB_OUTPUT_FORMAT_CHANGED received");
+                    sp<AMessage> format;
+                    if (!msg->findMessage("format", &format) || format == nullptr) {
+                        ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
+                        break;
+                    }
+                    sp<FrameDecoder> frameDecoder = mFrameDecoder.promote();
+                    if (frameDecoder != nullptr) {
+                        frameDecoder->handleOutputFormatChangeAsync(format);
+                    }
+                    break;
+                }
+                case MediaCodec::CB_ERROR: {
+                    status_t err;
+                    int32_t actionCode;
+                    AString detail;
+                    if (!msg->findInt32("err", &err)) {
+                        ALOGE("CB_ERROR: err is expected.");
+                        break;
+                    }
+                    if (!msg->findInt32("actionCode", &actionCode)) {
+                        ALOGE("CB_ERROR: actionCode is expected.");
+                        break;
+                    }
+                    msg->findString("detail", &detail);
+                    ALOGE("Codec reported error(0x%x/%s), actionCode(%d), detail(%s)", err,
+                          StrMediaError(err).c_str(), actionCode, detail.c_str());
+                    break;
+                }
+                default:
+                    ALOGE("kWhatCallbackNotify: callbackID(%d) is unexpected.", callbackId);
+                    break;
+            }
+            break;
+        default:
+            ALOGE("unexpected message received: %s", msg->debugString().c_str());
+            break;
+    }
+}
+
+void InputBufferIndexQueue::enqueue(int32_t index) {
+    std::scoped_lock<std::mutex> lock(mMutex);
+    mQueue.push(index);
+    mCondition.notify_one();
+}
+
+bool InputBufferIndexQueue::dequeue(int32_t* index, int32_t timeOutUs) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    bool hasAvailableIndex = mCondition.wait_for(lock, std::chrono::microseconds(timeOutUs),
+                                                 [this] { return !mQueue.empty(); });
+    if (hasAvailableIndex) {
+        *index = mQueue.front();
+        mQueue.pop();
+        return true;
+    } else {
+        return false;
+    }
+}
+
 //static
 sp<IMemory> FrameDecoder::getMetadataOnly(
         const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail, uint32_t bitDepth) {
@@ -281,6 +385,7 @@
         const sp<MetaData> &trackMeta,
         const sp<IMediaSource> &source)
     : mComponentName(componentName),
+      mUseBlockModel(false),
       mTrackMeta(trackMeta),
       mSource(source),
       mDstFormat(OMX_COLOR_Format16bitRGB565),
@@ -290,6 +395,10 @@
 }
 
 FrameDecoder::~FrameDecoder() {
+    if (mHandler != NULL) {
+        mAsyncLooper->stop();
+        mAsyncLooper->unregisterHandler(mHandler->id());
+    }
     if (mDecoder != NULL) {
         mDecoder->release();
         mSource->stop();
@@ -333,8 +442,18 @@
         return (decoder.get() == NULL) ? NO_MEMORY : err;
     }
 
+    if (mUseBlockModel) {
+        mAsyncLooper = new ALooper;
+        mAsyncLooper->start();
+        mHandler = new AsyncCodecHandler(wp<FrameDecoder>(this));
+        mAsyncLooper->registerHandler(mHandler);
+        sp<AMessage> callbackMsg = new AMessage(kWhatCallbackNotify, mHandler);
+        decoder->setCallback(callbackMsg);
+    }
+
     err = decoder->configure(
-            videoFormat, mSurface, NULL /* crypto */, 0 /* flags */);
+            videoFormat, mSurface, NULL /* crypto */,
+            mUseBlockModel ? MediaCodec::CONFIGURE_FLAG_USE_BLOCK_MODEL : 0 /* flags */);
     if (err != OK) {
         ALOGW("configure returned error %d (%s)", err, asString(err));
         decoder->release();
@@ -362,10 +481,18 @@
 sp<IMemory> FrameDecoder::extractFrame(FrameRect *rect) {
     ScopedTrace trace(ATRACE_TAG, "FrameDecoder::ExtractFrame");
     status_t err = onExtractRect(rect);
-    if (err == OK) {
+    if (err != OK) {
+        ALOGE("onExtractRect error %d", err);
+        return NULL;
+    }
+
+    if (!mUseBlockModel) {
         err = extractInternal();
+    } else {
+        err = extractInternalUsingBlockModel();
     }
     if (err != OK) {
+        ALOGE("extractInternal error %d", err);
         return NULL;
     }
 
@@ -380,6 +507,7 @@
         ALOGE("decoder is not initialized");
         return NO_INIT;
     }
+
     do {
         size_t index;
         int64_t ptsUs = 0LL;
@@ -433,7 +561,8 @@
                         (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
                         mediaBuffer->range_length());
 
-                onInputReceived(codecBuffer, mediaBuffer->meta_data(), mFirstSample, &flags);
+                onInputReceived(codecBuffer->data(), codecBuffer->size(), mediaBuffer->meta_data(),
+                                mFirstSample, &flags);
                 mFirstSample = false;
             }
 
@@ -487,11 +616,14 @@
                         ALOGE("failed to get output buffer %zu", index);
                         break;
                     }
+                    uint8_t* frameData = videoFrameBuffer->data();
+                    sp<ABuffer> imageData;
+                    videoFrameBuffer->meta()->findBuffer("image-data", &imageData);
                     if (mSurface != nullptr) {
                         mDecoder->renderOutputBufferAndRelease(index);
-                        err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
+                        err = onOutputReceived(frameData, imageData, mOutputFormat, ptsUs, &done);
                     } else {
-                        err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done);
+                        err = onOutputReceived(frameData, imageData, mOutputFormat, ptsUs, &done);
                         mDecoder->releaseOutputBuffer(index);
                     }
                 } else {
@@ -510,6 +642,75 @@
     return err;
 }
 
+status_t FrameDecoder::extractInternalUsingBlockModel() {
+    status_t err = OK;
+    MediaBufferBase* mediaBuffer = NULL;
+    int64_t ptsUs = 0LL;
+    uint32_t flags = 0;
+    int32_t index;
+    mHandleOutputBufferAsyncDone = false;
+
+    err = mSource->read(&mediaBuffer, &mReadOptions);
+    mReadOptions.clearSeekTo();
+    if (err != OK) {
+        ALOGW("Input Error: err=%d", err);
+        if (mediaBuffer) {
+            mediaBuffer->release();
+        }
+        return err;
+    }
+
+    size_t inputSize = mediaBuffer->range_length();
+    std::shared_ptr<C2LinearBlock> block =
+            MediaCodec::FetchLinearBlock(inputSize, {std::string{mComponentName.c_str()}});
+    C2WriteView view{block->map().get()};
+    if (view.error() != C2_OK) {
+        ALOGE("Fatal error: failed to allocate and map a block");
+        mediaBuffer->release();
+        return NO_MEMORY;
+    }
+    if (inputSize > view.capacity()) {
+        ALOGE("Fatal error: allocated block is too small "
+              "(input size %zu; block cap %u)",
+              inputSize, view.capacity());
+        mediaBuffer->release();
+        return BAD_VALUE;
+    }
+    CHECK(mediaBuffer->meta_data().findInt64(kKeyTime, &ptsUs));
+    memcpy(view.base(), (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
+           inputSize);
+    std::shared_ptr<C2Buffer> c2Buffer =
+            C2Buffer::CreateLinearBuffer(block->share(0, inputSize, C2Fence{}));
+    onInputReceived(view.base(), inputSize, mediaBuffer->meta_data(), true /* firstSample */,
+                    &flags);
+    flags |= MediaCodec::BUFFER_FLAG_EOS;
+    mediaBuffer->release();
+
+    std::vector<AccessUnitInfo> infoVec;
+    infoVec.emplace_back(flags, inputSize, ptsUs);
+    sp<BufferInfosWrapper> infos = new BufferInfosWrapper{std::move(infoVec)};
+
+    if (!mInputBufferIndexQueue.dequeue(&index, kAsyncBufferTimeOutUs)) {
+        ALOGE("No available input buffer index for async mode.");
+        return TIMED_OUT;
+    }
+
+    AString errorDetailMsg;
+    ALOGD("QueueLinearBlock: index=%d size=%zu ts=%" PRId64 " us flags=%x",
+            index, inputSize, ptsUs,flags);
+    err = mDecoder->queueBuffer(index, c2Buffer, infos, nullptr, &errorDetailMsg);
+    if (err != OK) {
+        ALOGE("failed to queueBuffer (err %d): %s", err, errorDetailMsg.c_str());
+        return err;
+    }
+
+    // wait for handleOutputBufferAsync() to finish
+    std::unique_lock _lk(mMutex);
+    mOutputFramePending.wait_for(_lk, std::chrono::microseconds(kAsyncBufferTimeOutUs),
+                                 [this] { return mHandleOutputBufferAsyncDone; });
+    return mHandleOutputBufferAsyncDone ? OK : TIMED_OUT;
+}
+
 //////////////////////////////////////////////////////////////////////
 
 VideoFrameDecoder::VideoFrameDecoder(
@@ -525,6 +726,81 @@
       mDefaultSampleDurationUs(0) {
 }
 
+status_t FrameDecoder::handleOutputFormatChangeAsync(sp<AMessage> format) {
+    // Here format is MediaCodec's internal copy of output format.
+    // Make a copy since the client might modify it.
+    mOutputFormat = format->dup();
+    ALOGD("receive output format in async mode: %s", mOutputFormat->debugString().c_str());
+    return OK;
+}
+
+status_t FrameDecoder::handleInputBufferAsync(int32_t index) {
+    mInputBufferIndexQueue.enqueue(index);
+    return OK;
+}
+
+status_t FrameDecoder::handleOutputBufferAsync(int32_t index, int64_t timeUs) {
+    if (mHandleOutputBufferAsyncDone) {
+        // we have already processed an output buffer, skip others
+        return OK;
+    }
+
+    status_t err = OK;
+    sp<MediaCodecBuffer> videoFrameBuffer;
+    err = mDecoder->getOutputBuffer(index, &videoFrameBuffer);
+    if (err != OK || videoFrameBuffer == nullptr) {
+        ALOGE("failed to get output buffer %d", index);
+        return err;
+    }
+
+    bool onOutputReceivedDone = false;
+    if (mSurface != nullptr) {
+        mDecoder->renderOutputBufferAndRelease(index);
+        // frameData and imgObj will be fetched by captureSurface() inside onOutputReceived()
+        // explicitly pass null here
+        err = onOutputReceived(nullptr, nullptr, mOutputFormat, timeUs, &onOutputReceivedDone);
+    } else {
+        // get stride and frame data for block model buffer
+        std::shared_ptr<C2Buffer> c2buffer = videoFrameBuffer->asC2Buffer();
+        if (!c2buffer
+                || c2buffer->data().type() != C2BufferData::GRAPHIC
+                || c2buffer->data().graphicBlocks().size() == 0u) {
+            ALOGE("C2Buffer precond fail");
+            return ERROR_MALFORMED;
+        }
+
+        std::unique_ptr<const C2GraphicView> view(std::make_unique<const C2GraphicView>(
+            c2buffer->data().graphicBlocks()[0].map().get()));
+        GraphicView2MediaImageConverter converter(*view, mOutputFormat, false /* copy */);
+        if (converter.initCheck() != OK) {
+            ALOGE("Converter init failed: %d", converter.initCheck());
+            return NO_INIT;
+        }
+
+        uint8_t* frameData = converter.wrap()->data();
+        sp<ABuffer> imageData = converter.imageData();
+        if (imageData != nullptr) {
+            mOutputFormat->setBuffer("image-data", imageData);
+            MediaImage2 *img = (MediaImage2*) imageData->data();
+            if (img->mNumPlanes > 0 && img->mType != img->MEDIA_IMAGE_TYPE_UNKNOWN) {
+                int32_t stride = img->mPlane[0].mRowInc;
+                mOutputFormat->setInt32(KEY_STRIDE, stride);
+                ALOGD("updating stride = %d", stride);
+            }
+        }
+
+        err = onOutputReceived(frameData, imageData, mOutputFormat, timeUs, &onOutputReceivedDone);
+        mDecoder->releaseOutputBuffer(index);
+    }
+
+    if (err == OK && onOutputReceivedDone) {
+        std::lock_guard _lm(mMutex);
+        mHandleOutputBufferAsyncDone = true;
+        mOutputFramePending.notify_one();
+    }
+    return err;
+}
+
 sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions(
         int64_t frameTimeUs, int seekMode,
         MediaSource::ReadOptions *options,
@@ -575,8 +851,13 @@
     bool isSeekingClosest = (mSeekMode == MediaSource::ReadOptions::SEEK_CLOSEST)
             || (mSeekMode == MediaSource::ReadOptions::SEEK_FRAME_INDEX);
     if (!isSeekingClosest) {
-        videoFormat->setInt32("android._num-input-buffers", 1);
-        videoFormat->setInt32("android._num-output-buffers", 1);
+        if (mComponentName.startsWithIgnoreCase("c2.")) {
+            mUseBlockModel = android::media::codec::provider_->thumbnail_block_model();
+        } else {
+            // OMX Codec
+            videoFormat->setInt32("android._num-input-buffers", 1);
+            videoFormat->setInt32("android._num-output-buffers", 1);
+        }
     }
 
     if (isHDR(videoFormat)) {
@@ -601,9 +882,8 @@
     return videoFormat;
 }
 
-status_t VideoFrameDecoder::onInputReceived(
-        const sp<MediaCodecBuffer> &codecBuffer,
-        MetaDataBase &sampleMeta, bool firstSample, uint32_t *flags) {
+status_t VideoFrameDecoder::onInputReceived(uint8_t* data, size_t size, MetaDataBase& sampleMeta,
+                                            bool firstSample, uint32_t* flags) {
     bool isSeekingClosest = (mSeekMode == MediaSource::ReadOptions::SEEK_CLOSEST)
             || (mSeekMode == MediaSource::ReadOptions::SEEK_FRAME_INDEX);
 
@@ -612,10 +892,7 @@
         ALOGV("Seeking closest: targetTimeUs=%lld", (long long)mTargetTimeUs);
     }
 
-    if (!isSeekingClosest
-            && ((mIsAvc && IsIDR(codecBuffer->data(), codecBuffer->size()))
-            || (mIsHevc && IsIDR(
-            codecBuffer->data(), codecBuffer->size())))) {
+    if (!isSeekingClosest && ((mIsAvc && IsIDR(data, size)) || (mIsHevc && IsIDR(data, size)))) {
         // Only need to decode one IDR frame, unless we're seeking with CLOSEST
         // option, in which case we need to actually decode to targetTimeUs.
         *flags |= MediaCodec::BUFFER_FLAG_EOS;
@@ -630,7 +907,8 @@
 }
 
 status_t VideoFrameDecoder::onOutputReceived(
-        const sp<MediaCodecBuffer> &videoFrameBuffer,
+        uint8_t* frameData,
+        sp<ABuffer> imgObj,
         const sp<AMessage> &outputFormat,
         int64_t timeUs, bool *done) {
     int64_t durationUs = mDefaultSampleDurationUs;
@@ -703,7 +981,6 @@
         }
 
         mFrame = static_cast<VideoFrame*>(frameMem->unsecurePointer());
-
         setFrame(frameMem);
     }
 
@@ -712,7 +989,7 @@
     if (mCaptureLayer != nullptr) {
         return captureSurface();
     }
-    ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
+    ColorConverter colorConverter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
 
     uint32_t standard, range, transfer;
     if (!outputFormat->findInt32("color-standard", (int32_t*)&standard)) {
@@ -724,22 +1001,25 @@
     if (!outputFormat->findInt32("color-transfer", (int32_t*)&transfer)) {
         transfer = 0;
     }
-    sp<ABuffer> imgObj;
-    if (videoFrameBuffer->meta()->findBuffer("image-data", &imgObj)) {
+
+    if (imgObj != nullptr) {
         MediaImage2 *imageData = nullptr;
         imageData = (MediaImage2 *)(imgObj.get()->data());
         if (imageData != nullptr) {
-            converter.setSrcMediaImage2(*imageData);
+            colorConverter.setSrcMediaImage2(*imageData);
         }
     }
     if (srcFormat == COLOR_FormatYUV420Flexible && imgObj.get() == nullptr) {
         return ERROR_UNSUPPORTED;
     }
-    converter.setSrcColorSpace(standard, range, transfer);
-    if (converter.isValid()) {
+    colorConverter.setSrcColorSpace(standard, range, transfer);
+    if (colorConverter.isValid()) {
         ScopedTrace trace(ATRACE_TAG, "FrameDecoder::ColorConverter");
-        converter.convert(
-                (const uint8_t *)videoFrameBuffer->data(),
+        if (frameData == nullptr) {
+            ALOGD("frameData is null for ColorConverter");
+        }
+        colorConverter.convert(
+                (const uint8_t *)frameData,
                 width, height, stride,
                 crop_left, crop_top, crop_right, crop_bottom,
                 mFrame->getFlattenedData(),
@@ -955,7 +1235,8 @@
 }
 
 status_t MediaImageDecoder::onOutputReceived(
-        const sp<MediaCodecBuffer> &videoFrameBuffer,
+        uint8_t* frameData,
+        sp<ABuffer> imgObj,
         const sp<AMessage> &outputFormat, int64_t /*timeUs*/, bool *done) {
     if (outputFormat == NULL) {
         return ERROR_MALFORMED;
@@ -1008,8 +1289,8 @@
     if (!outputFormat->findInt32("color-transfer", (int32_t*)&transfer)) {
         transfer = 0;
     }
-    sp<ABuffer> imgObj;
-    if (videoFrameBuffer->meta()->findBuffer("image-data", &imgObj)) {
+
+    if (imgObj != nullptr) {
         MediaImage2 *imageData = nullptr;
         imageData = (MediaImage2 *)(imgObj.get()->data());
         if (imageData != nullptr) {
@@ -1058,7 +1339,7 @@
 
     if (converter.isValid()) {
         converter.convert(
-                (const uint8_t *)videoFrameBuffer->data(),
+                (const uint8_t *)frameData,
                 width, height, stride,
                 crop_left, crop_top, crop_right, crop_bottom,
                 mFrame->getFlattenedData(),
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 15188b0..3aa0107 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -53,6 +53,8 @@
 #include <media/esds/ESDS.h>
 #include "include/HevcUtils.h"
 
+#include <com_android_media_editing_flags.h>
+
 #ifndef __predict_false
 #define __predict_false(exp) __builtin_expect((exp) != 0, 0)
 #endif
@@ -3776,6 +3778,12 @@
             if (mStszTableEntries->count() == 0) {
                 mFirstSampleTimeRealUs = systemTime() / 1000;
                 if (timestampUs < 0 && mFirstSampleStartOffsetUs == 0) {
+                    if (WARN_UNLESS(timestampUs != INT64_MIN, "for %s track", trackName)) {
+                        copy->release();
+                        mSource->stop();
+                        mIsMalformed = true;
+                        break;
+                    }
                     mFirstSampleStartOffsetUs = -timestampUs;
                     timestampUs = 0;
                 }
@@ -4938,6 +4946,8 @@
             // Track with start offset.
             ALOGV("Tracks starting > 0");
             int32_t editDurationTicks = 0;
+            int32_t trackStartOffsetBFramesUs = getMinCttsOffsetTimeUs() - kMaxCttsOffsetTimeUs;
+            ALOGV("trackStartOffsetBFramesUs:%" PRId32, trackStartOffsetBFramesUs);
             if (mMinCttsOffsetTicks == mMaxCttsOffsetTicks) {
                 // Video with no B frame or non-video track.
                 editDurationTicks =
@@ -4946,8 +4956,6 @@
                 ALOGV("editDuration:%" PRId64 "us", (trackStartOffsetUs + movieStartOffsetBFramesUs));
             } else {
                 // Track with B frame.
-                int32_t trackStartOffsetBFramesUs = getMinCttsOffsetTimeUs() - kMaxCttsOffsetTimeUs;
-                ALOGV("trackStartOffsetBFramesUs:%" PRId32, trackStartOffsetBFramesUs);
                 editDurationTicks =
                         ((trackStartOffsetUs + movieStartOffsetBFramesUs +
                           trackStartOffsetBFramesUs) * mvhdTimeScale + 5E5) / 1E6;
@@ -4961,7 +4969,15 @@
             } else if (editDurationTicks < 0) {
                 // Only video tracks with B Frames would hit this case.
                 ALOGV("Edit list entry to negate start offset by B frames in other tracks");
-                addOneElstTableEntry(tkhdDurationTicks, std::abs(editDurationTicks), 1, 0);
+                if (com::android::media::editing::flags::
+                        stagefrightrecorder_enable_b_frames()) {
+                    int32_t mediaTimeTicks =
+                            ((trackStartOffsetUs + movieStartOffsetBFramesUs +
+                              trackStartOffsetBFramesUs) * mTimeScale - 5E5) / 1E6;
+                    addOneElstTableEntry(tkhdDurationTicks, std::abs(mediaTimeTicks), 1, 0);
+                } else {
+                    addOneElstTableEntry(tkhdDurationTicks, std::abs(editDurationTicks), 1, 0);
+                }
             } else {
                 ALOGV("No edit list entry needed for this track");
             }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index d0d5cca..eea5242 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -487,7 +487,7 @@
                                     .id = getId(mClient),
                                     .name = mCodecName,
                                     .importance = mImportance};
-        return std::move(clientInfo);
+        return clientInfo;
     }
 
 private:
@@ -2459,7 +2459,12 @@
             mediametrics_setInt32(nextMetricsHandle, kCodecCrypto, 1);
         }
     } else if (mFlags & kFlagIsSecure) {
-        ALOGW("Crypto or descrambler should be given for secure codec");
+        if (android::media::codec::provider_->secure_codecs_require_crypto()) {
+            mErrorLog.log(LOG_TAG, "Crypto or descrambler must be given for secure codec");
+            return INVALID_OPERATION;
+        } else {
+            ALOGW("Crypto or descrambler should be given for secure codec");
+        }
     }
 
     if (mConfigureMsg != nullptr) {
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index 6fb9232..c18ab94 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -332,7 +332,7 @@
                 <!-- profiles and levels:  ProfileBaseline : Level3 -->
                 <Limit name="block-count" range="1-1620" />
                 <Limit name="blocks-per-second" range="1-40500" />
-                <Limit name="bitrate" range="1-2000000" />
+                <Limit name="bitrate" range="1-10000000" />
             </Variant>
             <Feature name="intra-refresh" />
             <!-- Video Quality control -->
diff --git a/media/libstagefright/include/FrameDecoder.h b/media/libstagefright/include/FrameDecoder.h
index e417324..94c201f 100644
--- a/media/libstagefright/include/FrameDecoder.h
+++ b/media/libstagefright/include/FrameDecoder.h
@@ -18,12 +18,15 @@
 #define FRAME_DECODER_H_
 
 #include <memory>
+#include <mutex>
+#include <queue>
 #include <vector>
 
-#include <media/stagefright/foundation/AString.h>
-#include <media/stagefright/foundation/ABase.h>
-#include <media/stagefright/MediaSource.h>
 #include <media/openmax/OMX_Video.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AString.h>
 #include <ui/GraphicTypes.h>
 
 namespace android {
@@ -34,11 +37,23 @@
 class MediaCodecBuffer;
 class Surface;
 class VideoFrame;
+struct AsyncCodecHandler;
 
 struct FrameRect {
     int32_t left, top, right, bottom;
 };
 
+struct InputBufferIndexQueue {
+public:
+    void enqueue(int32_t index);
+    bool dequeue(int32_t* index, int32_t timeOutUs);
+
+private:
+    std::queue<int32_t> mQueue;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+};
+
 struct FrameDecoder : public RefBase {
     FrameDecoder(
             const AString &componentName,
@@ -53,7 +68,19 @@
             const sp<MetaData> &trackMeta, int colorFormat,
             bool thumbnail = false, uint32_t bitDepth = 0);
 
+    status_t handleInputBufferAsync(int32_t index);
+    status_t handleOutputBufferAsync(int32_t index, int64_t timeUs);
+    status_t handleOutputFormatChangeAsync(sp<AMessage> format);
+
+    enum {
+        kWhatCallbackNotify,
+    };
+
 protected:
+    AString mComponentName;
+    sp<AMessage> mOutputFormat;
+    bool mUseBlockModel;
+
     virtual ~FrameDecoder();
 
     virtual sp<AMessage> onGetFormatAndSeekOptions(
@@ -64,14 +91,12 @@
 
     virtual status_t onExtractRect(FrameRect *rect) = 0;
 
-    virtual status_t onInputReceived(
-            const sp<MediaCodecBuffer> &codecBuffer,
-            MetaDataBase &sampleMeta,
-            bool firstSample,
-            uint32_t *flags) = 0;
+    virtual status_t onInputReceived(uint8_t* data, size_t size, MetaDataBase& sampleMeta,
+                                     bool firstSample, uint32_t* flags) = 0;
 
     virtual status_t onOutputReceived(
-            const sp<MediaCodecBuffer> &videoFrameBuffer,
+            uint8_t* data,
+            sp<ABuffer> imgObj,
             const sp<AMessage> &outputFormat,
             int64_t timeUs,
             bool *done) = 0;
@@ -83,7 +108,6 @@
     void setFrame(const sp<IMemory> &frameMem) { mFrameMemory = frameMem; }
 
 private:
-    AString mComponentName;
     sp<MetaData> mTrackMeta;
     sp<IMediaSource> mSource;
     OMX_COLOR_FORMATTYPE mDstFormat;
@@ -92,17 +116,32 @@
     sp<IMemory> mFrameMemory;
     MediaSource::ReadOptions mReadOptions;
     sp<MediaCodec> mDecoder;
-    sp<AMessage> mOutputFormat;
+    sp<AsyncCodecHandler> mHandler;
+    sp<ALooper> mAsyncLooper;
     bool mHaveMoreInputs;
     bool mFirstSample;
+    bool mHandleOutputBufferAsyncDone;
     sp<Surface> mSurface;
+    std::mutex mMutex;
+    std::condition_variable mOutputFramePending;
+    InputBufferIndexQueue mInputBufferIndexQueue;
 
     status_t extractInternal();
+    status_t extractInternalUsingBlockModel();
 
     DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder);
 };
 struct FrameCaptureLayer;
 
+struct AsyncCodecHandler : public AHandler {
+public:
+    explicit AsyncCodecHandler(const wp<FrameDecoder>& frameDecoder);
+    virtual void onMessageReceived(const sp<AMessage>& msg);
+
+private:
+    wp<FrameDecoder> mFrameDecoder;
+};
+
 struct VideoFrameDecoder : public FrameDecoder {
     VideoFrameDecoder(
             const AString &componentName,
@@ -121,14 +160,12 @@
         return (rect == NULL) ? OK : ERROR_UNSUPPORTED;
     }
 
-    virtual status_t onInputReceived(
-            const sp<MediaCodecBuffer> &codecBuffer,
-            MetaDataBase &sampleMeta,
-            bool firstSample,
-            uint32_t *flags) override;
+    virtual status_t onInputReceived(uint8_t* data, size_t size, MetaDataBase& sampleMeta,
+                                     bool firstSample, uint32_t* flags) override;
 
     virtual status_t onOutputReceived(
-            const sp<MediaCodecBuffer> &videoFrameBuffer,
+            uint8_t* data,
+            sp<ABuffer> imgObj,
             const sp<AMessage> &outputFormat,
             int64_t timeUs,
             bool *done) override;
@@ -162,14 +199,13 @@
 
     virtual status_t onExtractRect(FrameRect *rect) override;
 
-    virtual status_t onInputReceived(
-            const sp<MediaCodecBuffer> &codecBuffer __unused,
-            MetaDataBase &sampleMeta __unused,
-            bool firstSample __unused,
-            uint32_t *flags __unused) override { return OK; }
+    virtual status_t onInputReceived(uint8_t* __unused, size_t __unused,
+                                     MetaDataBase& sampleMeta __unused, bool firstSample __unused,
+                                     uint32_t* flags __unused) override { return OK; }
 
     virtual status_t onOutputReceived(
-            const sp<MediaCodecBuffer> &videoFrameBuffer,
+            uint8_t* data,
+            sp<ABuffer> imgObj,
             const sp<AMessage> &outputFormat,
             int64_t timeUs,
             bool *done) override;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
index 4e4aa75..b1cf665 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecConstants.h
@@ -562,6 +562,30 @@
     }
 }
 
+inline constexpr int32_t DTS_HDProfileHRA = 0x1;
+inline constexpr int32_t DTS_HDProfileLBR = 0x2;
+inline constexpr int32_t DTS_HDProfileMA = 0x4;
+
+inline static const char *asString_Dts_HDProfile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case DTS_HDProfileHRA:  return "HRA";
+        case DTS_HDProfileLBR:  return "LBR";
+        case DTS_HDProfileMA:   return "MA";
+        default:                return def;
+    }
+}
+
+inline constexpr int32_t DTS_UHDProfileP1 = 0x1;
+inline constexpr int32_t DTS_UHDProfileP2 = 0x2;
+
+inline static const char *asString_Dts_UHDProfile(int32_t i, const char *def = "??") {
+    switch (i) {
+        case DTS_UHDProfileP1:  return "P1";
+        case DTS_UHDProfileP2:  return "P2";
+        default:                return def;
+    }
+}
+
 inline constexpr int32_t BITRATE_MODE_CBR = 2;
 inline constexpr int32_t BITRATE_MODE_CBR_FD = 3;
 inline constexpr int32_t BITRATE_MODE_CQ = 0;
@@ -729,8 +753,13 @@
 inline constexpr char MIMETYPE_AUDIO_FLAC[] = "audio/flac";
 inline constexpr char MIMETYPE_AUDIO_MSGSM[] = "audio/gsm";
 inline constexpr char MIMETYPE_AUDIO_AC3[] = "audio/ac3";
+inline constexpr char MIMETYPE_AUDIO_AC4[] = "audio/ac4";
 inline constexpr char MIMETYPE_AUDIO_EAC3[] = "audio/eac3";
+inline constexpr char MIMETYPE_AUDIO_EAC3_JOC[] = "audio/eac3-joc";
 inline constexpr char MIMETYPE_AUDIO_SCRAMBLED[] = "audio/scrambled";
+inline constexpr char MIMETYPE_AUDIO_DTS[] = "audio/vnd.dts";
+inline constexpr char MIMETYPE_AUDIO_DTS_HD[] = "audio/vnd.dts.hd";
+inline constexpr char MIMETYPE_AUDIO_DTS_UHD[] = "audio/vnd.dts.uhd";
 
 inline constexpr char MIMETYPE_IMAGE_ANDROID_HEIC[] = "image/vnd.android.heic";
 
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 4183023..4ab5d10 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -619,6 +619,13 @@
                 if (!isValidOMXParam(outParams)) {
                     return OMX_ErrorBadParameter;
                 }
+                if (offsetof(DescribeHDR10PlusInfoParams, nValue) + outParams->nParamSize >
+                    outParams->nSize) {
+                    ALOGE("b/329641908: too large param size; nParamSize=%u nSize=%u",
+                          outParams->nParamSize, outParams->nSize);
+                    android_errorWriteLog(0x534e4554, "329641908");
+                    return OMX_ErrorBadParameter;
+                }
 
                 outParams->nParamSizeUsed = info->size();
 
diff --git a/media/libstagefright/webm/WebmWriter.cpp b/media/libstagefright/webm/WebmWriter.cpp
index ca862b0..151ce7c 100644
--- a/media/libstagefright/webm/WebmWriter.cpp
+++ b/media/libstagefright/webm/WebmWriter.cpp
@@ -290,7 +290,7 @@
     // Max file duration limit is set
     if (mMaxFileDurationLimitUs != 0) {
         if (bitRate > 0) {
-            int64_t size2 = ((mMaxFileDurationLimitUs * bitRate * 6) / 1000 / 8000000);
+            int64_t size2 = ((mMaxFileDurationLimitUs / 1000) * bitRate * 6) / 8000000;
             if (mMaxFileSizeLimitBytes != 0 && mIsFileSizeLimitExplicitlyRequested) {
                 // When both file size and duration limits are set,
                 // we use the smaller limit of the two.
diff --git a/media/libstagefright/writer_fuzzers/Android.bp b/media/libstagefright/writer_fuzzers/Android.bp
index 58aa7cd..840c6b3c 100644
--- a/media/libstagefright/writer_fuzzers/Android.bp
+++ b/media/libstagefright/writer_fuzzers/Android.bp
@@ -24,6 +24,7 @@
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
+    default_team: "trendy_team_android_media_solutions_editing",
 }
 
 cc_defaults {
@@ -35,14 +36,17 @@
         "include",
     ],
     static_libs: [
+        "com.android.media.flags.editing-aconfig-cc",
         "liblog",
-        "libstagefright_foundation",
         "libstagefright",
+        "libstagefright_foundation",
     ],
     shared_libs: [
+        "libaconfig_storage_read_api_cc",
         "libbinder",
         "libcutils",
         "libutils",
+        "server_configurable_flags",
     ],
 }
 
@@ -96,9 +100,9 @@
 }
 
 cc_fuzz {
-    name : "mpeg4_writer_fuzzer",
-    defaults : ["writer-fuzzer-defaults"],
-    srcs : [
+    name: "mpeg4_writer_fuzzer",
+    defaults: ["writer-fuzzer-defaults"],
+    srcs: [
         "mpeg4_writer_fuzzer.cpp",
     ],
     static_libs: [
@@ -107,9 +111,9 @@
 }
 
 cc_fuzz {
-    name : "ogg_writer_fuzzer",
-    defaults : ["writer-fuzzer-defaults"],
-    srcs : [
+    name: "ogg_writer_fuzzer",
+    defaults: ["writer-fuzzer-defaults"],
+    srcs: [
         "ogg_writer_fuzzer.cpp",
     ],
     static_libs: [
@@ -118,9 +122,9 @@
 }
 
 cc_fuzz {
-    name : "webm_writer_fuzzer",
-    defaults : ["writer-fuzzer-defaults"],
-    srcs : [
+    name: "webm_writer_fuzzer",
+    defaults: ["writer-fuzzer-defaults"],
+    srcs: [
         "webm_writer_fuzzer.cpp",
     ],
     static_libs: [
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 8c1ef3b..bd11326 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -1069,7 +1069,7 @@
         codec.rank = rank;
     }
 
-    codec.variantSet = variants;
+    codec.variantSet.insert(variants.begin(), variants.end());
 
     // we allow sets of domains...
     for (const std::string &domain : domains) {
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index 6ea40e3..d916fd1 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -54,6 +54,8 @@
 mediaserver_cc_binary {
     name: "mediaserver",
 
+    defaults: ["libcodec2_hal_selection"],
+
     srcs: ["main_mediaserver.cpp"],
 
     shared_libs: [
@@ -61,6 +63,7 @@
         "libicu",
         "libfmq",
         "libbinder",
+        "libbinder_ndk",
         "libhidlbase",
         "liblog",
         "libmediaplayerservice",
diff --git a/media/mediaserver/main_mediaserver.cpp b/media/mediaserver/main_mediaserver.cpp
index 026847a..8a62f30 100644
--- a/media/mediaserver/main_mediaserver.cpp
+++ b/media/mediaserver/main_mediaserver.cpp
@@ -17,11 +17,12 @@
 
 #define LOG_TAG "mediaserver"
 //#define LOG_NDEBUG 0
-
+#include <android/binder_process.h>
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
 #include <hidl/HidlTransportSupport.h>
+#include <codec2/common/HalSelection.h>
 #include <utils/Log.h>
 #include "RegisterExtensions.h"
 
@@ -30,6 +31,14 @@
 
 using namespace android;
 
+namespace {
+    constexpr int kCodecThreadPoolCount = 16;
+
+    // This is the default thread count for binder thread pool
+    // if the thread count is not configured.
+    constexpr int kDefaultBinderThreadPoolCount = 15;
+}; // anonymous
+
 int main(int argc __unused, char **argv __unused)
 {
     signal(SIGPIPE, SIG_IGN);
@@ -40,8 +49,14 @@
     MediaPlayerService::instantiate();
     ResourceManagerService::instantiate();
     registerExtensions();
-    ::android::hardware::configureRpcThreadpool(16, false);
+
+    bool aidl = ::android::IsCodec2AidlHalSelected();
+    if (!aidl) {
+        ::android::hardware::configureRpcThreadpool(kCodecThreadPoolCount, false);
+    } else {
+        ABinderProcess_setThreadPoolMaxThreadCount(
+                kCodecThreadPoolCount + kDefaultBinderThreadPoolCount);
+    }
     ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
-    ::android::hardware::joinRpcThreadpool();
 }
diff --git a/media/module/bufferpool/2.0/BufferPoolClient.cpp b/media/module/bufferpool/2.0/BufferPoolClient.cpp
index cda23ff..66d11fa 100644
--- a/media/module/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/module/bufferpool/2.0/BufferPoolClient.cpp
@@ -762,6 +762,10 @@
     } else {
         connection = mRemoteConnection;
     }
+    if (!connection) {
+        ALOGE("connection null: fetchBufferHandle()");
+        return ResultStatus::CRITICAL_ERROR;
+    }
     ResultStatus status;
     Return<void> transResult = connection->fetch(
             transactionId, bufferId,
diff --git a/media/module/codecs/amrnb/common/include/abs_s.h b/media/module/codecs/amrnb/common/include/abs_s.h
deleted file mode 100644
index e92eaf4..0000000
--- a/media/module/codecs/amrnb/common/include/abs_s.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Pathname: ./gsm-amr/c/include/abs_s.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for abs_s function.
-
- Description: Updated template to make it build for Symbian.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the abs_s function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef ABS_S_H
-#define ABS_S_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-    Word16 abs_s(Word16 var1);
-
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* ABS_S_H */
-
-
diff --git a/media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h b/media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
index 8f0867a..8817621 100644
--- a/media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
+++ b/media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
@@ -120,15 +120,11 @@
     {
         Word32 L_sum;
 
-        L_sum = L_var1 + L_var2;
-
-        if ((L_var1 ^ L_var2) >= 0)
+        if (__builtin_add_overflow(L_var1, L_var2, &L_sum))
         {
-            if ((L_sum ^ L_var1) < 0)
-            {
-                L_sum = (L_var1 < 0) ? MIN_32 : MAX_32;
-                *pOverflow = 1;
-            }
+            // saturating...
+            L_sum = (L_var1 < 0) ? MIN_32 : MAX_32;
+            *pOverflow = 1;
         }
 
         return (L_sum);
@@ -160,15 +156,11 @@
     {
         Word32 L_diff;
 
-        L_diff = L_var1 - L_var2;
-
-        if ((L_var1 ^ L_var2) < 0)
+        if (__builtin_sub_overflow(L_var1, L_var2, &L_diff))
         {
-            if ((L_diff ^ L_var1) & MIN_32)
-            {
-                L_diff = (L_var1 < 0L) ? MIN_32 : MAX_32;
-                *pOverflow = 1;
-            }
+            // saturating...
+            L_diff = (L_var1 < 0L) ? MIN_32 : MAX_32;
+            *pOverflow = 1;
         }
 
         return (L_diff);
@@ -204,16 +196,12 @@
         result = (Word32) var1 * var2;
         if (result != (Word32) 0x40000000L)
         {
-            L_sum = (result << 1) + L_var3;
-
             /* Check if L_sum and L_var_3 share the same sign */
-            if ((L_var3 ^ result) > 0)
+            if (__builtin_add_overflow((result << 1), L_var3, &L_sum))
             {
-                if ((L_sum ^ L_var3) < 0)
-                {
-                    L_sum = (L_var3 < 0) ? MIN_32 : MAX_32;
-                    *pOverflow = 1;
-                }
+                // saturating...
+                L_sum = (L_var3 < 0) ? MIN_32 : MAX_32;
+                *pOverflow = 1;
             }
         }
         else
@@ -345,14 +333,10 @@
         product32 = ((Word32) L_var1_hi * L_var2_lo) >> 15;
 
         /* L_product = L_mac (L_product, result, 1, pOverflow); */
-        L_sum = L_product + (product32 << 1);
-
-        if ((L_product ^ product32) > 0)
+        if (__builtin_add_overflow(L_product, (product32 << 1), &L_sum))
         {
-            if ((L_sum ^ L_product) < 0)
-            {
-                L_sum = (L_product < 0) ? MIN_32 : MAX_32;
-            }
+            // saturating...
+            L_sum = (L_product < 0) ? MIN_32 : MAX_32;
         }
 
         L_product = L_sum;
@@ -361,14 +345,10 @@
         product32 = ((Word32) L_var1_lo * L_var2_hi) >> 15;
 
         /* L_product = L_mac (L_product, result, 1, pOverflow); */
-        L_sum = L_product + (product32 << 1);
-
-        if ((L_product ^ product32) > 0)
+        if (__builtin_add_overflow(L_product, (product32 << 1), &L_sum))
         {
-            if ((L_sum ^ L_product) < 0)
-            {
-                L_sum = (L_product < 0) ? MIN_32 : MAX_32;
-            }
+            // saturating...
+            L_sum = (L_product < 0) ? MIN_32 : MAX_32;
         }
         return (L_sum);
     }
@@ -416,15 +396,11 @@
 
         result = ((Word32)L_var1_lo * var2) >> 15;
 
-        L_sum  =  L_product + (result << 1);
-
-        if ((L_product ^ result) > 0)
+        if (__builtin_add_overflow(L_product, (result << 1), &L_sum))
         {
-            if ((L_sum ^ L_product) < 0)
-            {
-                L_sum = (L_product < 0) ? MIN_32 : MAX_32;
-                *pOverflow = 1;
-            }
+            // saturating...
+            L_sum = (L_product < 0) ? MIN_32 : MAX_32;
+            *pOverflow = 1;
         }
         return (L_sum);
 
diff --git a/media/module/codecs/amrnb/common/include/l_add.h b/media/module/codecs/amrnb/common/include/l_add.h
deleted file mode 100644
index 136b914..0000000
--- a/media/module/codecs/amrnb/common/include/l_add.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/l_add.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_add function.
-
- Description: Changed function prototype declaration. A pointer to the overflow
-              flag is being passed in as a parameter instead of using global
-              data.
-
- Description: Updated template. Changed paramter name from overflow to
-              pOverflow
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: Providing support for ARM and Linux-ARM assembly instructions.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_add function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_ADD_H
-#define L_ADD_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
-    {
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-        __asm
-        {
-            QADD result, L_var1, L_var2
-        }
-        return(result);
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    __inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
-    {
-        register Word32 ra = L_var1;
-        register Word32 rb = L_var2;
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("qadd %0, %1, %2"
-             : "=r"(result)
-                             : "r"(ra), "r"(rb)
-                            );
-        return (result);
-
-    }
-
-#else /* C EQUIVALENT */
-
-
-    static inline Word32 L_add(register Word32 L_var1, register Word32 L_var2, Flag *pOverflow)
-    {
-        Word32 L_sum;
-
-        L_sum = L_var1 + L_var2;
-
-        if ((L_var1 ^ L_var2) >= 0)
-        {
-            if ((L_sum ^ L_var1) < 0)
-            {
-                L_sum = (L_var1 < 0) ? MIN_32 : MAX_32;
-                *pOverflow = 1;
-            }
-        }
-
-        return (L_sum);
-    }
-
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_ADD_H_ */
diff --git a/media/module/codecs/amrnb/common/include/l_add_c.h b/media/module/codecs/amrnb/common/include/l_add_c.h
deleted file mode 100644
index 3585a3c..0000000
--- a/media/module/codecs/amrnb/common/include/l_add_c.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/l_add_c.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_add_c function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag and carry flag is passed into the
-              function. Updated template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_add_c function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_ADD_C_H
-#define L_ADD_C_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-    Word32 L_add_c(Word32 L_var1, Word32 L_var2, Flag *pOverflow, Flag *pCarry);
-
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_ADD_C_H_ */
-
-
diff --git a/media/module/codecs/amrnb/common/include/l_mac.h b/media/module/codecs/amrnb/common/include/l_mac.h
deleted file mode 100644
index b4af3aa..0000000
--- a/media/module/codecs/amrnb/common/include/l_mac.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
- Filename: /audio/gsm_amr/c/include/l_mac.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_mac function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: 1. Updated the function to include ARM and Linux-ARM assembly
-                 instructions.
-              2. Added OSCL_UNUSED_ARG(pOverflow) to remove compiler warnings.
-
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_mac function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_MAC_H
-#define L_MAC_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        Word32 result;
-        Word32 L_sum;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        __asm {SMULBB result, var1, var2}
-        __asm {QDADD L_sum, L_var3, result}
-        return (L_sum);
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    static inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        register Word32 ra = L_var3;
-        register Word32 rb = var1;
-        register Word32 rc = var2;
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(result)
-                             : "r"(rb), "r"(rc)
-                            );
-
-        asm volatile("qdadd %0, %1, %2"
-             : "=r"(rc)
-                             : "r"(ra), "r"(result)
-                            );
-
-        return (rc);
-    }
-
-#else /* C_EQUIVALENT */
-
-    __inline Word32 L_mac(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        Word32 result;
-        Word32 L_sum;
-        result = (Word32) var1 * var2;
-        if (result != (Word32) 0x40000000L)
-        {
-            L_sum = (result << 1) + L_var3;
-
-            /* Check if L_sum and L_var_3 share the same sign */
-            if ((L_var3 ^ result) > 0)
-            {
-                if ((L_sum ^ L_var3) < 0)
-                {
-                    L_sum = (L_var3 < 0) ? MIN_32 : MAX_32;
-                    *pOverflow = 1;
-                }
-            }
-        }
-        else
-        {
-            *pOverflow = 1;
-            L_sum = MAX_32;
-        }
-        return (L_sum);
-    }
-
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_MAC_H_ */
-
-
diff --git a/media/module/codecs/amrnb/common/include/l_msu.h b/media/module/codecs/amrnb/common/include/l_msu.h
deleted file mode 100644
index 3bafb00..0000000
--- a/media/module/codecs/amrnb/common/include/l_msu.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
- Filename: /audio/gsm_amr/c/include/l_msu.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_msu function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: Providing support for ARM and Linux-ARM assembly instructions.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_msu function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_MSU_H
-#define L_MSU_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-#include    "l_mult.h"
-#include    "l_sub.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        Word32 product;
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        __asm
-        {
-            SMULBB product, var1, var2
-            QDSUB  result, L_var3, product
-        }
-
-        return (result);
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    __inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        register Word32 ra = L_var3;
-        register Word32 rb = var1;
-        register Word32 rc = var2;
-        Word32 product;
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(product)
-                             : "r"(rb), "r"(rc)
-                            );
-
-        asm volatile("qdsub %0, %1, %2"
-             : "=r"(result)
-                             : "r"(ra), "r"(product)
-                            );
-
-        return (result);
-    }
-
-#else /* C EQUIVALENT */
-
-    static inline Word32 L_msu(Word32 L_var3, Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        Word32 result;
-
-        result = L_mult(var1, var2, pOverflow);
-        result = L_sub(L_var3, result, pOverflow);
-
-        return (result);
-    }
-
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_MSU_H_ */
diff --git a/media/module/codecs/amrnb/common/include/l_mult.h b/media/module/codecs/amrnb/common/include/l_mult.h
deleted file mode 100644
index 061df60..0000000
--- a/media/module/codecs/amrnb/common/include/l_mult.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/l_mult.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_mult function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: Providing support for ARM and Linux-ARM assembly instructions.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_mult function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_MULT_H
-#define L_MULT_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        Word32 result;
-        Word32 product;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        __asm
-        {
-            SMULBB product, var1, var2
-            QADD   result, product, product
-        }
-
-        return (result);
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    __inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        register Word32 ra = var1;
-        register Word32 rb = var2;
-        Word32 result;
-        Word32 product;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(product)
-                             : "r"(ra), "r"(rb)
-                            );
-
-        asm volatile("qadd %0, %1, %2"
-             : "=r"(result)
-                             : "r"(product), "r"(product)
-                            );
-
-        return(result);
-    }
-
-#else /* C EQUIVALENT */
-
-    static inline Word32 L_mult(Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        register Word32 L_product;
-
-        L_product = (Word32) var1 * var2;
-
-        if (L_product != (Word32) 0x40000000L)
-        {
-            L_product <<= 1;          /* Multiply by 2 */
-        }
-        else
-        {
-            *pOverflow = 1;
-            L_product = MAX_32;
-        }
-
-        return (L_product);
-    }
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_MULT_H */
-
diff --git a/media/module/codecs/amrnb/common/include/l_shl.h b/media/module/codecs/amrnb/common/include/l_shl.h
deleted file mode 100644
index 7b9fdb1..0000000
--- a/media/module/codecs/amrnb/common/include/l_shl.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/l_shl.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_shl function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_shl function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_SHL_H
-#define L_SHL_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-    Word32 L_shl(Word32 L_var1, Word16 var2, Flag *pOverflow);
-
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_SHL_H_ */
-
-
-
diff --git a/media/module/codecs/amrnb/common/include/l_shr.h b/media/module/codecs/amrnb/common/include/l_shr.h
deleted file mode 100644
index ef22073..0000000
--- a/media/module/codecs/amrnb/common/include/l_shr.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
- Filename: /audio/gsm_amr/c/include/l_shr.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_shr function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_shr function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_SHR_H
-#define L_SHR_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-    Word32 L_shr(Word32 L_var1, Word16 var2, Flag *pOverflow);
-
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_SHR_H_ */
-
-
-
diff --git a/media/module/codecs/amrnb/common/include/l_sub.h b/media/module/codecs/amrnb/common/include/l_sub.h
deleted file mode 100644
index 97d7538..0000000
--- a/media/module/codecs/amrnb/common/include/l_sub.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/l_sub.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for L_sub function.
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: Providing support for ARM and Linux-ARM assembly instructions.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the L_sub function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef L_SUB_H
-#define L_SUB_H
-
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 L_sub(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
-    {
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        __asm
-        {
-            QSUB result, L_var1, L_var2
-        }
-
-        return(result);
-
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    __inline Word32 L_sub(Word32 L_var1, Word32 L_var2, Flag *pOverflow)
-    {
-        register Word32 ra = L_var1;
-        register Word32 rb = L_var2;
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("qsub %0, %1, %2"
-             : "=r"(result)
-                             : "r"(ra), "r"(rb)
-                            );
-
-        return (result);
-    }
-
-#else /* C EQUIVALENT */
-
-    static inline Word32 L_sub(register Word32 L_var1, register Word32 L_var2,
-                               register Flag *pOverflow)
-    {
-        Word32 L_diff;
-
-        L_diff = L_var1 - L_var2;
-
-        if ((L_var1 ^ L_var2) < 0)
-        {
-            if ((L_diff ^ L_var1) & MIN_32)
-            {
-                L_diff = (L_var1 < 0L) ? MIN_32 : MAX_32;
-                *pOverflow = 1;
-            }
-        }
-
-        return (L_diff);
-    }
-
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _L_SUB_H_ */
-
-
diff --git a/media/module/codecs/amrnb/common/include/mpy_32.h b/media/module/codecs/amrnb/common/include/mpy_32.h
deleted file mode 100644
index 03f36b2..0000000
--- a/media/module/codecs/amrnb/common/include/mpy_32.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/mpy_32.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Updated function prototype declaration to reflect new interface.
-              A pointer to overflow flag is passed into the function. Updated
-              template.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: Updated the function to include ARM and Linux-ARM assembly
-              instructions.
-
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the Mpy_32 function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef MPY_32_H
-#define MPY_32_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 Mpy_32(Word16 L_var1_hi,
-    Word16 L_var1_lo,
-    Word16 L_var2_hi,
-    Word16 L_var2_lo,
-    Flag   *pOverflow)
-
-    {
-        /*----------------------------------------------------------------------------
-        ; Define all local variables
-        ----------------------------------------------------------------------------*/
-        Word32 L_product;
-        Word32 L_sum;
-        Word32 product32;
-
-        OSCL_UNUSED_ARG(pOverflow);
-        /*----------------------------------------------------------------------------
-        ; Function body here
-        ----------------------------------------------------------------------------*/
-        /* L_product = L_mult (L_var1_hi, L_var2_hi, pOverflow);*/
-
-        __asm {SMULBB L_product, L_var1_hi, L_var2_hi}
-        __asm {QDADD L_product, 0, L_product}
-        __asm {SMULBB product32, L_var1_hi, L_var2_lo}
-        product32 >>= 15;
-        __asm {QDADD L_sum, L_product, product32}
-        L_product = L_sum;
-        __asm {SMULBB product32, L_var1_lo, L_var2_hi}
-        product32 >>= 15;
-        __asm {QDADD L_sum, L_product, product32}
-        return (L_sum);
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    static inline Word32 Mpy_32(Word16 L_var1_hi,
-                                Word16 L_var1_lo,
-                                Word16 L_var2_hi,
-                                Word16 L_var2_lo,
-                                Flag   *pOverflow)
-    {
-        register Word32 product32;
-        register Word32 L_sum;
-        register Word32 L_product, result;
-        register Word32 ra = L_var1_hi;
-        register Word32 rb = L_var1_lo;
-        register Word32 rc = L_var2_hi;
-        register Word32 rd = L_var2_lo;
-
-
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(L_product)
-                             : "r"(ra), "r"(rc)
-                            );
-        asm volatile("mov %0, #0"
-             : "=r"(result)
-                    );
-
-        asm volatile("qdadd %0, %1, %2"
-             : "=r"(L_sum)
-                             : "r"(result), "r"(L_product)
-                            );
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(product32)
-                             : "r"(ra), "r"(rd)
-                            );
-
-        asm volatile("mov %0, %1, ASR #15"
-             : "=r"(ra)
-                             : "r"(product32)
-                            );
-        asm volatile("qdadd %0, %1, %2"
-             : "=r"(L_product)
-                             : "r"(L_sum), "r"(ra)
-                            );
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(product32)
-                             : "r"(rb), "r"(rc)
-                            );
-
-        asm volatile("mov %0, %1, ASR #15"
-             : "=r"(rb)
-                             : "r"(product32)
-                            );
-
-        asm volatile("qdadd %0, %1, %2"
-             : "=r"(L_sum)
-                             : "r"(L_product), "r"(rb)
-                            );
-
-        return (L_sum);
-    }
-
-#else /* C_EQUIVALENT */
-
-    __inline Word32 Mpy_32(Word16 L_var1_hi,
-                           Word16 L_var1_lo,
-                           Word16 L_var2_hi,
-                           Word16 L_var2_lo,
-                           Flag   *pOverflow)
-    {
-        Word32 L_product;
-        Word32 L_sum;
-        Word32 product32;
-
-        OSCL_UNUSED_ARG(pOverflow);
-        L_product = (Word32) L_var1_hi * L_var2_hi;
-
-        if (L_product != (Word32) 0x40000000L)
-        {
-            L_product <<= 1;
-        }
-        else
-        {
-            L_product = MAX_32;
-        }
-
-        /* result = mult (L_var1_hi, L_var2_lo, pOverflow); */
-        product32 = ((Word32) L_var1_hi * L_var2_lo) >> 15;
-
-        /* L_product = L_mac (L_product, result, 1, pOverflow); */
-        L_sum = L_product + (product32 << 1);
-
-        if ((L_product ^ product32) > 0)
-        {
-            if ((L_sum ^ L_product) < 0)
-            {
-                L_sum = (L_product < 0) ? MIN_32 : MAX_32;
-            }
-        }
-
-        L_product = L_sum;
-
-        /* result = mult (L_var1_lo, L_var2_hi, pOverflow); */
-        product32 = ((Word32) L_var1_lo * L_var2_hi) >> 15;
-
-        /* L_product = L_mac (L_product, result, 1, pOverflow); */
-        L_sum = L_product + (product32 << 1);
-
-        if ((L_product ^ product32) > 0)
-        {
-            if ((L_sum ^ L_product) < 0)
-            {
-                L_sum = (L_product < 0) ? MIN_32 : MAX_32;
-            }
-        }
-
-        /*----------------------------------------------------------------------------
-        ; Return nothing or data or data pointer
-        ----------------------------------------------------------------------------*/
-        return (L_sum);
-    }
-
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MPY_32_H_ */
diff --git a/media/module/codecs/amrnb/common/include/mpy_32_16.h b/media/module/codecs/amrnb/common/include/mpy_32_16.h
deleted file mode 100644
index 7eaa741..0000000
--- a/media/module/codecs/amrnb/common/include/mpy_32_16.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
-  Filename: /audio/gsm_amr/c/include/mpy_32_16.h
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the Mpy_32_16 function.
-
-------------------------------------------------------------------------------
-*/
-
-/*----------------------------------------------------------------------------
-; CONTINUE ONLY IF NOT ALREADY DEFINED
-----------------------------------------------------------------------------*/
-#ifndef MPY_32_16_H
-#define MPY_32_16_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5) /* Instructions for ARM Assembly on ADS*/
-
-    __inline Word32 Mpy_32_16(Word16 L_var1_hi,
-    Word16 L_var1_lo,
-    Word16 var2,
-    Flag *pOverflow)
-    {
-
-        Word32 L_product;
-        Word32 L_sum;
-        Word32 result;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        __asm {SMULBB L_product, L_var1_hi, var2}
-        __asm {QDADD L_product, 0, L_product}
-        __asm {SMULBB result, L_var1_lo, var2}
-        result >>= 15;
-        __asm {QDADD L_sum, L_product, result}
-        return (L_sum);
-    }
-
-#elif defined(PV_ARM_GCC_V5) /* Instructions for ARM-linux cross-compiler*/
-
-    static inline Word32 Mpy_32_16(Word16 L_var1_hi,
-                                   Word16 L_var1_lo,
-                                   Word16 var2,
-                                   Flag *pOverflow)
-    {
-
-        register Word32 ra = L_var1_hi;
-        register Word32 rb = L_var1_lo;
-        register Word32 rc = var2;
-        Word32 result, L_product;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(L_product)
-                             : "r"(ra), "r"(rc)
-                            );
-        asm volatile("mov %0, #0"
-             : "=r"(result)
-                    );
-
-        asm volatile("qdadd %0, %1, %2"
-             : "=r"(L_product)
-                             : "r"(result), "r"(L_product)
-                            );
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(result)
-                             : "r"(rb), "r"(rc)
-                            );
-
-        asm volatile("mov %0, %1, ASR #15"
-             : "=r"(ra)
-                             : "r"(result)
-                            );
-        asm volatile("qdadd %0, %1, %2"
-             : "=r"(result)
-                             : "r"(L_product), "r"(ra)
-                            );
-
-        return (result);
-    }
-
-#else /* C_EQUIVALENT */
-    __inline Word32 Mpy_32_16(Word16 L_var1_hi,
-                              Word16 L_var1_lo,
-                              Word16 var2,
-                              Flag *pOverflow)
-    {
-
-        Word32 L_product;
-        Word32 L_sum;
-        Word32 result;
-        L_product = (Word32) L_var1_hi * var2;
-
-        if (L_product != (Word32) 0x40000000L)
-        {
-            L_product <<= 1;
-        }
-        else
-        {
-            *pOverflow = 1;
-            L_product = MAX_32;
-        }
-
-        result = ((Word32)L_var1_lo * var2) >> 15;
-
-        L_sum  =  L_product + (result << 1);
-
-        if ((L_product ^ result) > 0)
-        {
-            if ((L_sum ^ L_product) < 0)
-            {
-                L_sum = (L_product < 0) ? MIN_32 : MAX_32;
-                *pOverflow = 1;
-            }
-        }
-        return (L_sum);
-
-    }
-
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _MPY_32_16_H_ */
-
-
diff --git a/media/module/codecs/amrnb/common/include/mult.h b/media/module/codecs/amrnb/common/include/mult.h
deleted file mode 100644
index 6927eba..0000000
--- a/media/module/codecs/amrnb/common/include/mult.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/*
-
- Filename: /audio/gsm_amr/c/include/mult.h
-
-------------------------------------------------------------------------------
- REVISION HISTORY
-
- Description: Created separate header file for mult function.
-
- Description: Changed prototype of the mult() function. Instead of using global
-              a pointer to overflow flag is now passed into the function.
-
- Description: Updated copyright information.
-              Updated variable name from "overflow" to "pOverflow" to match
-              with original function declaration.
-
- Description: Moved _cplusplus #ifdef after Include section.
-
- Description: Providing support for ARM and Linux-ARM assembly instructions.
-
- Who:                       Date:
- Description:
-
-------------------------------------------------------------------------------
- INCLUDE DESCRIPTION
-
- This file contains all the constant definitions and prototype definitions
- needed by the mult function.
-
-------------------------------------------------------------------------------
-*/
-
-#ifndef MULT_H
-#define MULT_H
-
-/*----------------------------------------------------------------------------
-; INCLUDES
-----------------------------------------------------------------------------*/
-
-#include    "basicop_malloc.h"
-
-/*--------------------------------------------------------------------------*/
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /*----------------------------------------------------------------------------
-    ; MACROS
-    ; Define module specific macros here
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; DEFINES
-    ; Include all pre-processor statements here.
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; EXTERNAL VARIABLES REFERENCES
-    ; Declare variables used in this module but defined elsewhere
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; SIMPLE TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; ENUMERATED TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; STRUCTURES TYPEDEF'S
-    ----------------------------------------------------------------------------*/
-
-    /*----------------------------------------------------------------------------
-    ; GLOBAL FUNCTION DEFINITIONS
-    ; Function Prototype declaration
-    ----------------------------------------------------------------------------*/
-#if defined(PV_ARM_V5)
-
-    __inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        Word32 product;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        __asm
-        {
-            SMULBB product, var1, var2
-            MOV    product, product, ASR #15
-            CMP    product, 0x7FFF
-            MOVGE  product, 0x7FFF
-        }
-
-        return ((Word16) product);
-    }
-
-#elif defined(PV_ARM_GCC_V5)
-
-    __inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        register Word32 ra = var1;
-        register Word32 rb = var2;
-        Word32 product;
-        Word32 temp = 0x7FFF;
-
-        OSCL_UNUSED_ARG(pOverflow);
-
-        asm volatile("smulbb %0, %1, %2"
-             : "=r"(product)
-                             : "r"(ra), "r"(rb)
-                            );
-        asm volatile("mov %0, %1, ASR #15"
-             : "=r"(product)
-                             : "r"(product)
-                            );
-        asm volatile("cmp %0, %1"
-             : "=r"(product)
-                             : "r"(temp)
-                            );
-        asm volatile("movge %0, %1"
-             : "=r"(product)
-                             : "r"(temp)
-                            );
-
-        return ((Word16) product);
-    }
-
-#else /* C EQUIVALENT */
-
-    static inline Word16 mult(Word16 var1, Word16 var2, Flag *pOverflow)
-    {
-        register Word32 product;
-
-        product = ((Word32) var1 * var2) >> 15;
-
-        /* Saturate result (if necessary). */
-        /* var1 * var2 >0x00007fff is the only case */
-        /* that saturation occurs. */
-
-        if (product > 0x00007fffL)
-        {
-            *pOverflow = 1;
-            product = (Word32) MAX_16;
-        }
-
-
-        /* Return the product as a 16 bit value by type casting Word32 to Word16 */
-
-        return ((Word16) product);
-    }
-
-#endif
-    /*----------------------------------------------------------------------------
-    ; END
-    ----------------------------------------------------------------------------*/
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* _MULT_H_ */
-
diff --git a/media/module/codecs/amrnb/common/include/n_proc.h b/media/module/codecs/amrnb/common/include/n_proc.h
deleted file mode 100644
index e5738c1..0000000
--- a/media/module/codecs/amrnb/common/include/n_proc.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* ------------------------------------------------------------------
- * Copyright (C) 1998-2009 PacketVideo
- *
- * 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.
- * -------------------------------------------------------------------
- */
-/****************************************************************************************
-Portions of this file are derived from the following 3GPP standard:
-
-    3GPP TS 26.073
-    ANSI-C code for the Adaptive Multi-Rate (AMR) speech codec
-    Available from http://www.3gpp.org
-
-(C) 2004, 3GPP Organizational Partners (ARIB, ATIS, CCSA, ETSI, TTA, TTC)
-Permission to distribute, modify and use this file under the standard license
-terms listed above has been obtained from the copyright holder.
-****************************************************************************************/
-/* $Id $ */
-
-void proc_head(char *mes);
diff --git a/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp b/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
index af62074..984baf8 100644
--- a/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
+++ b/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
@@ -22,6 +22,7 @@
 
 #include <audio_utils/sndfile.h>
 #include <stdio.h>
+#include <fstream>
 
 #include "gsmamr_dec.h"
 
@@ -40,7 +41,7 @@
 
 static AmrnbDecTestEnvironment *gEnv = nullptr;
 
-class AmrnbDecoderTest : public ::testing::TestWithParam<string> {
+class AmrnbDecoderTest : public ::testing::TestWithParam<std::tuple<string, string>> {
   public:
     AmrnbDecoderTest() : mFpInput(nullptr) {}
 
@@ -54,6 +55,7 @@
     FILE *mFpInput;
     SNDFILE *openOutputFile(SF_INFO *sfInfo);
     int32_t DecodeFrames(void *amrHandle, SNDFILE *outFileHandle, int32_t frameCount = INT32_MAX);
+    bool compareBinaryFiles(const std::string& refFilePath, const std::string& outFilePath);
 };
 
 SNDFILE *AmrnbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
@@ -97,6 +99,42 @@
     return 0;
 }
 
+bool AmrnbDecoderTest::compareBinaryFiles(const std::string &refFilePath,
+                                          const std::string &outFilePath) {
+    std::ifstream refFile(refFilePath, std::ios::binary | std::ios::ate);
+    std::ifstream outFile(outFilePath, std::ios::binary | std::ios::ate);
+    assert(refFile.is_open() && "Error opening reference file " + refFilePath);
+    assert(outFile.is_open() && "Error opening output file " + outFilePath);
+
+    std::streamsize refFileSize = refFile.tellg();
+    std::streamsize outFileSize = outFile.tellg();
+    if (refFileSize != outFileSize) {
+        ALOGE("Error, File size mismatch: Reference file size = %td bytes,"
+              " but output file size = %td bytes.", refFileSize, outFileSize);
+        return false;
+    }
+
+    refFile.seekg(0, std::ios::beg);
+    outFile.seekg(0, std::ios::beg);
+    constexpr std::streamsize kBufferSize = 16 * 1024;
+    char refBuffer[kBufferSize];
+    char outBuffer[kBufferSize];
+
+    while (refFile && outFile) {
+        refFile.read(refBuffer, kBufferSize);
+        outFile.read(outBuffer, kBufferSize);
+
+        std::streamsize refBytesRead = refFile.gcount();
+        std::streamsize outBytesRead = outFile.gcount();
+
+        if (refBytesRead != outBytesRead || memcmp(refBuffer, outBuffer, refBytesRead) != 0) {
+            ALOGE("Error, File content mismatch.");
+            return false;
+        }
+    }
+    return true;
+}
+
 TEST_F(AmrnbDecoderTest, CreateAmrnbDecoderTest) {
     void *amrHandle;
     int32_t status = GSMInitDecode(&amrHandle, (Word8 *)"AMRNBDecoder");
@@ -106,7 +144,7 @@
 }
 
 TEST_P(AmrnbDecoderTest, DecodeTest) {
-    string inputFile = gEnv->getRes() + GetParam();
+    string inputFile = gEnv->getRes() + std::get<0>(GetParam());
     mFpInput = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
 
@@ -126,10 +164,15 @@
     sf_close(outFileHandle);
     GSMDecodeFrameExit(&amrHandle);
     ASSERT_EQ(amrHandle, nullptr) << "Error deleting AMR-NB decoder";
+
+    string refFilePath = gEnv->getRes() + std::get<1>(GetParam());
+    ASSERT_TRUE(compareBinaryFiles(refFilePath, OUTPUT_FILE))
+       << "Error, Binary file comparison failed: Output file " << OUTPUT_FILE
+       << " does not match the reference file " << refFilePath << ".";
 }
 
 TEST_P(AmrnbDecoderTest, ResetDecodeTest) {
-    string inputFile = gEnv->getRes() + GetParam();
+    string inputFile = gEnv->getRes() + std::get<0>(GetParam());
     mFpInput = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
 
@@ -159,8 +202,24 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(AmrnbDecoderTestAll, AmrnbDecoderTest,
-                         ::testing::Values(("bbb_8000hz_1ch_8kbps_amrnb_30sec.amrnb"),
-                                           ("sine_amrnb_1ch_12kbps_8000hz.amrnb")));
+                         ::testing::Values(std::make_tuple(
+                                                   "bbb_8000hz_1ch_8kbps_amrnb_30sec.amrnb",
+                                                   "bbb_8000hz_1ch_8kbps_amrnb_30sec_ref.pcm"),
+                                           std::make_tuple(
+                                                   "sine_amrnb_1ch_12kbps_8000hz.amrnb",
+                                                   "sine_amrnb_1ch_12kbps_8000hz_ref.pcm"),
+                                           std::make_tuple(
+                                                   "trim_8000hz_1ch_12kpbs_amrnb_200ms.amrnb",
+                                                   "trim_8000hz_1ch_12kpbs_amrnb_200ms_ref.pcm"),
+                                           std::make_tuple(
+                                                   "bbb_8kHz_1ch_4.75kbps_amrnb_3sec.amrnb",
+                                                   "bbb_8kHz_1ch_4.75kbps_amrnb_3sec_ref.pcm"),
+                                           std::make_tuple(
+                                                   "bbb_8kHz_1ch_10kbps_amrnb_1sec.amrnb",
+                                                   "bbb_8kHz_1ch_10kbps_amrnb_1sec_ref.pcm"),
+                                           std::make_tuple(
+                                                   "bbb_8kHz_1ch_12.2kbps_amrnb_3sec.amrnb",
+                                                   "bbb_8kHz_1ch_12.2kbps_amrnb_3sec_ref.pcm")));
 
 int main(int argc, char **argv) {
     gEnv = new AmrnbDecTestEnvironment();
diff --git a/media/module/codecs/amrnb/dec/test/AndroidTest.xml b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
index 539fa5c..7b2ba15 100644
--- a/media/module/codecs/amrnb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
@@ -23,17 +23,17 @@
     <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"/>
+        <option name="version" value="2.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="media-folder-name" value="AmrnbDecoderTest-2.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 /sdcard/test/AmrnbDecoderTest-1.0/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrnbDecoderTest-2.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrnb/dec/test/DynamicConfig.xml b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
index 701a752..02b869a 100644
--- a/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
+++ b/media/module/codecs/amrnb/dec/test/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest-1.0.zip</value>
+            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest-2.0.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/media/module/codecs/amrnb/dec/test/README.md b/media/module/codecs/amrnb/dec/test/README.md
index 41fb80a..ea54975 100644
--- a/media/module/codecs/amrnb/dec/test/README.md
+++ b/media/module/codecs/amrnb/dec/test/README.md
@@ -22,15 +22,15 @@
 adb push ${OUT}/data/nativetest/AmrnbDecoderTest/AmrnbDecoderTest /data/local/tmp/
 ```
 
-The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest-1.0.zip). Download, unzip and push these files into device for testing.
+The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest-2.0.zip). Download, unzip and push these files into device for testing.
 
 ```
-adb push AmrnbDecoderTest-1.0 /data/local/tmp/
+adb push AmrnbDecoderTest-2.0 /data/local/tmp/
 ```
 
 usage: AmrnbDecoderTest -P \<path_to_folder\>
 ```
-adb shell /data/local/tmp/AmrnbDecoderTest -P /data/local/tmp/AmrnbDecoderTest-1.0/
+adb shell /data/local/tmp/AmrnbDecoderTest -P /data/local/tmp/AmrnbDecoderTest-2.0/
 ```
 Alternatively, the test can also be run using atest command.
 
diff --git a/media/module/codecs/amrnb/enc/src/g_pitch.cpp b/media/module/codecs/amrnb/enc/src/g_pitch.cpp
index 5b80e2a..6f686fa 100644
--- a/media/module/codecs/amrnb/enc/src/g_pitch.cpp
+++ b/media/module/codecs/amrnb/enc/src/g_pitch.cpp
@@ -376,15 +376,11 @@
     {
         L_temp = ((Word32) * (p_xn++) * *(p_y1++));
         s1 = s;
-        s = s1 + L_temp;
 
-        if ((s1 ^ L_temp) > 0)
+        if (__builtin_add_overflow(s1, L_temp, &s))
         {
-            if ((s1 ^ s) < 0)
-            {
-                *pOverflow = 1;
-                break;
-            }
+            *pOverflow = 1;
+            break;
         }
     }
 
diff --git a/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp b/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
index fb72998..e3bd0e0 100644
--- a/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
+++ b/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
@@ -21,6 +21,7 @@
 
 #include <audio_utils/sndfile.h>
 #include <stdio.h>
+#include <fstream>
 
 #include "gsmamr_enc.h"
 
@@ -39,7 +40,7 @@
 
 static AmrnbEncTestEnvironment *gEnv = nullptr;
 
-class AmrnbEncoderTest : public ::testing::TestWithParam<pair<string, int32_t>> {
+class AmrnbEncoderTest : public ::testing::TestWithParam<tuple<string, int32_t, string>> {
   public:
     AmrnbEncoderTest() : mAmrEncHandle(nullptr) {}
 
@@ -53,6 +54,7 @@
     AmrNbEncState *mAmrEncHandle;
     int32_t EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
                          int32_t frameCount = INT32_MAX);
+    bool compareBinaryFiles(const string& refFilePath, const string& outFilePath);
 };
 
 int32_t AmrnbEncoderTest::EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
@@ -87,6 +89,42 @@
     return 0;
 }
 
+bool AmrnbEncoderTest::compareBinaryFiles(const std::string &refFilePath,
+                                          const std::string &outFilePath) {
+    std::ifstream refFile(refFilePath, std::ios::binary | std::ios::ate);
+    std::ifstream outFile(outFilePath, std::ios::binary | std::ios::ate);
+    assert(refFile.is_open() && "Error opening reference file " + refFilePath);
+    assert(outFile.is_open() && "Error opening output file " + outFilePath);
+
+    std::streamsize refFileSize = refFile.tellg();
+    std::streamsize outFileSize = outFile.tellg();
+    if (refFileSize != outFileSize) {
+        ALOGE("Error, File size mismatch: Reference file size = %td bytes,"
+              " but output file size = %td bytes.", refFileSize, outFileSize);
+        return false;
+    }
+
+    refFile.seekg(0, std::ios::beg);
+    outFile.seekg(0, std::ios::beg);
+    constexpr std::streamsize kBufferSize = 16 * 1024;
+    char refBuffer[kBufferSize];
+    char outBuffer[kBufferSize];
+
+    while (refFile && outFile) {
+        refFile.read(refBuffer, kBufferSize);
+        outFile.read(outBuffer, kBufferSize);
+
+        std::streamsize refBytesRead = refFile.gcount();
+        std::streamsize outBytesRead = outFile.gcount();
+
+        if (refBytesRead != outBytesRead || memcmp(refBuffer, outBuffer, refBytesRead) != 0) {
+            ALOGE("Error, File content mismatch.");
+            return false;
+        }
+    }
+    return true;
+}
+
 TEST_F(AmrnbEncoderTest, CreateAmrnbEncoderTest) {
     mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
     ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
@@ -111,7 +149,7 @@
     int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
     ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
 
-    string inputFile = gEnv->getRes() + GetParam().first;
+    string inputFile = gEnv->getRes() + std::get<0>(GetParam());
     FILE *fpInput = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
 
@@ -121,7 +159,7 @@
     // Write file header.
     fwrite("#!AMR\n", 1, 6, fpOutput);
 
-    int32_t mode = GetParam().second;
+    int32_t mode = std::get<1>(GetParam());
     int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput);
     ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
 
@@ -134,6 +172,11 @@
     free(mAmrEncHandle);
     mAmrEncHandle = nullptr;
     ALOGV("Successfully deleted encoder");
+
+    string refFilePath = gEnv->getRes() + std::get<2>(GetParam());
+    ASSERT_TRUE(compareBinaryFiles(refFilePath, OUTPUT_FILE))
+       << "Error, Binary file comparison failed: Output file " << OUTPUT_FILE
+       << " does not match the reference file " << refFilePath << ".";
 }
 
 TEST_P(AmrnbEncoderTest, ResetEncoderTest) {
@@ -142,7 +185,7 @@
     int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
     ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
 
-    string inputFile = gEnv->getRes() + GetParam().first;
+    string inputFile = gEnv->getRes() + std::get<0>(GetParam());
     FILE *fpInput = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
 
@@ -152,7 +195,7 @@
     // Write file header.
     fwrite("#!AMR\n", 1, 6, fpOutput);
 
-    int32_t mode = GetParam().second;
+    int32_t mode = std::get<1>(GetParam());
     // Encode kNumFrameReset first
     int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput, kNumFrameReset);
     ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
@@ -177,22 +220,23 @@
 
 // TODO: Add more test vectors
 INSTANTIATE_TEST_SUITE_P(AmrnbEncoderTestAll, AmrnbEncoderTest,
-                         ::testing::Values(make_pair("bbb_raw_1ch_8khz_s16le.raw", MR475),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR515),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR59),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR67),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR74),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR795),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR102),
-                                           make_pair("bbb_raw_1ch_8khz_s16le.raw", MR122),
-                                           make_pair("sinesweepraw.raw", MR475),
-                                           make_pair("sinesweepraw.raw", MR515),
-                                           make_pair("sinesweepraw.raw", MR59),
-                                           make_pair("sinesweepraw.raw", MR67),
-                                           make_pair("sinesweepraw.raw", MR74),
-                                           make_pair("sinesweepraw.raw", MR795),
-                                           make_pair("sinesweepraw.raw", MR102),
-                                           make_pair("sinesweepraw.raw", MR122)));
+    ::testing::Values(
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR475, "bbb_raw_1ch_8khz_s16le_MR475_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR515, "bbb_raw_1ch_8khz_s16le_MR515_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR59, "bbb_raw_1ch_8khz_s16le_MR59_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR67, "bbb_raw_1ch_8khz_s16le_MR67_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR74, "bbb_raw_1ch_8khz_s16le_MR74_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR795, "bbb_raw_1ch_8khz_s16le_MR795_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR102, "bbb_raw_1ch_8khz_s16le_MR102_ref.amrnb"),
+        make_tuple("bbb_raw_1ch_8khz_s16le.raw", MR122, "bbb_raw_1ch_8khz_s16le_MR122_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR475, "sinesweepraw_MR475_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR515, "sinesweepraw_MR515_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR59, "sinesweepraw_MR59_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR67, "sinesweepraw_MR67_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR74, "sinesweepraw_MR74_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR795, "sinesweepraw_MR795_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR102, "sinesweepraw_MR102_ref.amrnb"),
+        make_tuple("sinesweepraw.raw", MR122, "sinesweepraw_MR122_ref.amrnb")));
 
 int main(int argc, char **argv) {
     gEnv = new AmrnbEncTestEnvironment();
diff --git a/media/module/codecs/amrnb/enc/test/AndroidTest.xml b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
index 1509728..a325ee8 100644
--- a/media/module/codecs/amrnb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
@@ -23,17 +23,17 @@
     <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"/>
+        <option name="version" value="2.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="media-folder-name" value="AmrnbEncoderTest-2.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 /sdcard/test/AmrnbEncoderTest-1.0/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrnbEncoderTest-2.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrnb/enc/test/DynamicConfig.xml b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
index 713667a..fdc0daa 100644
--- a/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
+++ b/media/module/codecs/amrnb/enc/test/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest-1.0.zip</value>
+            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest-2.0.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/media/module/codecs/amrnb/enc/test/README.md b/media/module/codecs/amrnb/enc/test/README.md
index f896bd1..c7b9964 100644
--- a/media/module/codecs/amrnb/enc/test/README.md
+++ b/media/module/codecs/amrnb/enc/test/README.md
@@ -22,15 +22,15 @@
 adb push ${OUT}/data/nativetest/AmrnbEncoderTest/AmrnbEncoderTest /data/local/tmp/
 ```
 
-The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest-1.0.zip). Download, unzip and push these files into device for testing.
+The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest-2.0.zip). Download, unzip and push these files into device for testing.
 
 ```
-adb push AmrnbEncoderTest-1.0 /data/local/tmp/
+adb push AmrnbEncoderTest-2.0 /data/local/tmp/
 ```
 
 usage: AmrnbEncoderTest -P \<path_to_folder\>
 ```
-adb shell /data/local/tmp/AmrnbEncoderTest -P /data/local/tmp/AmrnbEncoderTest-1.0/
+adb shell /data/local/tmp/AmrnbEncoderTest -P /data/local/tmp/AmrnbEncoderTest-2.0/
 ```
 Alternatively, the test can also be run using atest command.
 
diff --git a/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
index 2cc88ce..c0e032f 100644
--- a/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
+++ b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
@@ -23,6 +23,7 @@
 #include <audio_utils/sndfile.h>
 #include <memory>
 #include <stdio.h>
+#include <fstream>
 
 #include "pvamrwbdecoder.h"
 #include "pvamrwbdecoder_api.h"
@@ -44,7 +45,7 @@
 
 static AmrwbDecTestEnvironment *gEnv = nullptr;
 
-class AmrwbDecoderTest : public ::testing::TestWithParam<string> {
+class AmrwbDecoderTest : public ::testing::TestWithParam<std::tuple<string, string>> {
   public:
     AmrwbDecoderTest() : mFpInput(nullptr) {}
 
@@ -59,6 +60,7 @@
     int32_t DecodeFrames(int16_t *decoderCookie, void *decoderBuf, SNDFILE *outFileHandle,
                          int32_t frameCount = INT32_MAX);
     SNDFILE *openOutputFile(SF_INFO *sfInfo);
+    bool compareBinaryFiles(const std::string& refFilePath, const std::string& outFilePath);
 };
 
 SNDFILE *AmrwbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
@@ -120,6 +122,42 @@
     return 0;
 }
 
+bool AmrwbDecoderTest::compareBinaryFiles(const std::string &refFilePath,
+                                          const std::string &outFilePath) {
+    std::ifstream refFile(refFilePath, std::ios::binary | std::ios::ate);
+    std::ifstream outFile(outFilePath, std::ios::binary | std::ios::ate);
+    assert(refFile.is_open() && "Error opening reference file " + refFilePath);
+    assert(outFile.is_open() && "Error opening output file " + outFilePath);
+
+    std::streamsize refFileSize = refFile.tellg();
+    std::streamsize outFileSize = outFile.tellg();
+    if (refFileSize != outFileSize) {
+        ALOGE("Error, File size mismatch: Reference file size = %td bytes,"
+               "but output file size = %td bytes", refFileSize, outFileSize);
+        return false;
+    }
+
+    refFile.seekg(0, std::ios::beg);
+    outFile.seekg(0, std::ios::beg);
+    constexpr std::streamsize kBufferSize = 16 * 1024;
+    char refBuffer[kBufferSize];
+    char outBuffer[kBufferSize];
+
+    while (refFile && outFile) {
+        refFile.read(refBuffer, kBufferSize);
+        outFile.read(outBuffer, kBufferSize);
+
+        std::streamsize refBytesRead = refFile.gcount();
+        std::streamsize outBytesRead = outFile.gcount();
+
+        if (refBytesRead != outBytesRead || memcmp(refBuffer, outBuffer, refBytesRead) != 0) {
+            ALOGE("Error, File content mismatch.");
+            return false;
+        }
+    }
+    return true;
+}
+
 TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
     std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
@@ -147,7 +185,7 @@
     pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
 
-    string inputFile = gEnv->getRes() + GetParam();
+    string inputFile = gEnv->getRes() + std::get<0>(GetParam());
     mFpInput = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
 
@@ -160,6 +198,10 @@
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     sf_close(outFileHandle);
+    string refFilePath = gEnv->getRes() + std::get<1>(GetParam());
+    ASSERT_TRUE(compareBinaryFiles(refFilePath, OUTPUT_FILE))
+    << "Error, Binary file comparison failed: Output file "
+    << OUTPUT_FILE << " does not match the reference file " << refFilePath << ".";
 }
 
 TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
@@ -173,7 +215,7 @@
     pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
 
-    string inputFile = gEnv->getRes() + GetParam();
+    string inputFile = gEnv->getRes() + std::get<0>(GetParam());
     mFpInput = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
 
@@ -198,8 +240,21 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
-                         ::testing::Values(("bbb_amrwb_1ch_14kbps_16000hz.amrwb"),
-                                           ("bbb_16000hz_1ch_9kbps_amrwb_30sec.amrwb")));
+                         ::testing::Values(std::make_tuple(
+                                                "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
+                                                "bbb_amrwb_1ch_14kbps_16000hz_ref.pcm"),
+                                           std::make_tuple(
+                                                "bbb_16000hz_1ch_9kbps_amrwb_30sec.amrwb",
+                                                "bbb_16000hz_1ch_9kbps_amrwb_30sec_ref.pcm"),
+                                           std::make_tuple(
+                                                "bbb_16kHz_1ch_16bps_1sec.amrwb",
+                                                "bbb_16kHz_1ch_16bps_1sec_ref.pcm"),
+                                           std::make_tuple(
+                                                "bbb_16kHz_1ch_6.6bps_3sec.amrwb",
+                                                "bbb_16kHz_1ch_6.6bps_3sec_ref.pcm"),
+                                           std::make_tuple(
+                                                "bbb_16kHz_1ch_23.85bps_3sec.amrwb",
+                                                "bbb_16kHz_1ch_23.85bps_3sec_ref.pcm")));
 
 int main(int argc, char **argv) {
     gEnv = new AmrwbDecTestEnvironment();
diff --git a/media/module/codecs/amrwb/dec/test/AndroidTest.xml b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
index 392df03..dbd1407 100644
--- a/media/module/codecs/amrwb/dec/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
@@ -23,17 +23,17 @@
     <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"/>
+        <option name="version" value="2.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="media-folder-name" value="AmrwbDecoderTest-2.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 /sdcard/test/AmrwbDecoderTest-1.0/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrwbDecoderTest-2.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrwb/dec/test/DynamicConfig.xml b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
index 506cc3d..52453ee 100644
--- a/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
+++ b/media/module/codecs/amrwb/dec/test/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest-1.0.zip</value>
+            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest-2.0.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/media/module/codecs/amrwb/dec/test/README.md b/media/module/codecs/amrwb/dec/test/README.md
index 8e77456..ed76051 100644
--- a/media/module/codecs/amrwb/dec/test/README.md
+++ b/media/module/codecs/amrwb/dec/test/README.md
@@ -22,15 +22,15 @@
 adb push ${OUT}/data/nativetest/AmrwbDecoderTest/AmrwbDecoderTest /data/local/tmp/
 ```
 
-The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest-1.0.zip). Download, unzip and push these files into device for testing.
+The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest-2.0.zip). Download, unzip and push these files into device for testing.
 
 ```
-adb push AmrwbDecoderTest-1.0 /data/local/tmp/
+adb push AmrwbDecoderTest-2.0 /data/local/tmp/
 ```
 
 usage: AmrwbDecoderTest -P \<path_to_folder\>
 ```
-adb shell /data/local/tmp/AmrwbDecoderTest -P /data/local/tmp/AmrwbDecoderTest-1.0/
+adb shell /data/local/tmp/AmrwbDecoderTest -P /data/local/tmp/AmrwbDecoderTest-2.0/
 ```
 Alternatively, the test can also be run using atest command.
 
diff --git a/media/module/codecs/amrwb/enc/inc/basic_op.h b/media/module/codecs/amrwb/enc/inc/basic_op.h
index 80ad7f1..8e740b4 100644
--- a/media/module/codecs/amrwb/enc/inc/basic_op.h
+++ b/media/module/codecs/amrwb/enc/inc/basic_op.h
@@ -569,13 +569,10 @@
 static_vo Word32 L_add (Word32 L_var1, Word32 L_var2)
 {
     Word32 L_var_out;
-    L_var_out = L_var1 + L_var2;
-    if (((L_var1 ^ L_var2) & MIN_32) == 0)
+    if (__builtin_add_overflow(L_var1, L_var2, &L_var_out))
     {
-        if ((L_var_out ^ L_var1) & MIN_32)
-        {
-            L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
-        }
+        // saturating...
+        L_var_out = (L_var1 < 0) ? MIN_32 : MAX_32;
     }
     return (L_var_out);
 }
@@ -616,13 +613,10 @@
 static_vo Word32 L_sub (Word32 L_var1, Word32 L_var2)
 {
     Word32 L_var_out;
-    L_var_out = L_var1 - L_var2;
-    if (((L_var1 ^ L_var2) & MIN_32) != 0)
+    if (__builtin_sub_overflow(L_var1, L_var2, &L_var_out))
     {
-        if ((L_var_out ^ L_var1) & MIN_32)
-        {
-            L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
-        }
+        // saturating...
+        L_var_out = (L_var1 < 0L) ? MIN_32 : MAX_32;
     }
     return (L_var_out);
 }
diff --git a/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp b/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
index 1a6ee27..dc9c1b1 100644
--- a/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
+++ b/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 
 #include <stdio.h>
+#include <fstream>
 
 #include "cmnMemory.h"
 #include "voAMRWB.h"
@@ -34,13 +35,15 @@
 
 static AmrwbEncTestEnvironment *gEnv = nullptr;
 
-class AmrwbEncoderTest : public ::testing::TestWithParam<tuple<string, int32_t, VOAMRWBFRAMETYPE>> {
+class AmrwbEncoderTest : public ::testing::TestWithParam<tuple<string, int32_t,
+                                                               VOAMRWBFRAMETYPE, string>> {
   public:
     AmrwbEncoderTest() : mEncoderHandle(nullptr) {
-        tuple<string, int32_t, VOAMRWBFRAMETYPE> params = GetParam();
+        tuple<string, int32_t, VOAMRWBFRAMETYPE, string> params = GetParam();
         mInputFile = gEnv->getRes() + get<0>(params);
         mMode = get<1>(params);
         mFrameType = get<2>(params);
+        refFilePath = gEnv->getRes() + get<3>(params);
         mMemOperator.Alloc = cmnMemAlloc;
         mMemOperator.Copy = cmnMemCopy;
         mMemOperator.Free = cmnMemFree;
@@ -66,8 +69,47 @@
     VO_CODEC_INIT_USERDATA mUserData;
     VO_HANDLE mEncoderHandle;
     int32_t mMode;
+    string refFilePath;
+
+    bool compareBinaryFiles(const string& refFilePath, const string& outFilePath);
 };
 
+bool AmrwbEncoderTest::compareBinaryFiles(const std::string &refFilePath,
+                                          const std::string &outFilePath) {
+    std::ifstream refFile(refFilePath, std::ios::binary | std::ios::ate);
+    std::ifstream outFile(outFilePath, std::ios::binary | std::ios::ate);
+    assert(refFile.is_open() && "Error opening reference file " + refFilePath);
+    assert(outFile.is_open() && "Error opening output file " + outFilePath);
+
+    std::streamsize refFileSize = refFile.tellg();
+    std::streamsize outFileSize = outFile.tellg();
+    if (refFileSize != outFileSize) {
+        ALOGE("Error, File size mismatch: Reference file size = %td bytes,"
+               "but output file size = %td bytes", refFileSize, outFileSize);
+        return false;
+    }
+
+    refFile.seekg(0, std::ios::beg);
+    outFile.seekg(0, std::ios::beg);
+    constexpr std::streamsize kBufferSize = 16 * 1024;
+    char refBuffer[kBufferSize];
+    char outBuffer[kBufferSize];
+
+    while (refFile && outFile) {
+        refFile.read(refBuffer, kBufferSize);
+        outFile.read(outBuffer, kBufferSize);
+
+        std::streamsize refBytesRead = refFile.gcount();
+        std::streamsize outBytesRead = outFile.gcount();
+
+        if (refBytesRead != outBytesRead || memcmp(refBuffer, outBuffer, refBytesRead) != 0) {
+            ALOGE("Error, File content mismatch.");
+            return false;
+        }
+    }
+    return true;
+}
+
 TEST_P(AmrwbEncoderTest, CreateAmrwbEncoderTest) {
     int32_t status = voGetAMRWBEncAPI(&mApiHandle);
     ASSERT_EQ(status, VO_ERR_NONE) << "Failed to get api handle";
@@ -152,38 +194,69 @@
     if (fpOutput) {
         fclose(fpOutput);
     }
+
+    ASSERT_TRUE(compareBinaryFiles(refFilePath, OUTPUT_FILE))
+    << "Error, Binary file comparison failed: Output file "
+    << OUTPUT_FILE << " does not match the reference file " << refFilePath << ".";
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        AmrwbEncoderTestAll, AmrwbEncoderTest,
-        ::testing::Values(
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_DEFAULT),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_ITU),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_RFC3267),
-                make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_RFC3267)));
+    AmrwbEncoderTestAll, AmrwbEncoderTest,
+    ::testing::Values(
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD66_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD885_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1265_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1425_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1585_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1825_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1985_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2305_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_DEFAULT,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2385_VOAMRWB_DEFAULT_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD66_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD885_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1265_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1425_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1585_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1825_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1985_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2305_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_ITU,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2385_VOAMRWB_ITU_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD66_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD885_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1265_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1425_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1585_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1825_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1985_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2305_VOAMRWB_RFC3267_ref.amrwb"),
+        make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_RFC3267,
+                    "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2385_VOAMRWB_RFC3267_ref.amrwb")));
 
 int main(int argc, char **argv) {
     gEnv = new AmrwbEncTestEnvironment();
diff --git a/media/module/codecs/amrwb/enc/test/AndroidTest.xml b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
index 8822cb2..1f4121f 100644
--- a/media/module/codecs/amrwb/enc/test/AndroidTest.xml
+++ b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
@@ -23,17 +23,17 @@
     <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"/>
+        <option name="version" value="2.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="media-folder-name" value="AmrwbEncoderTest-2.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 /sdcard/test/AmrwbEncoderTest-1.0/" />
+        <option name="native-test-flag" value="-P /sdcard/test/AmrwbEncoderTest-2.0/" />
     </test>
 </configuration>
diff --git a/media/module/codecs/amrwb/enc/test/DynamicConfig.xml b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
index a0b6218..59701ea 100644
--- a/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
+++ b/media/module/codecs/amrwb/enc/test/DynamicConfig.xml
@@ -15,6 +15,6 @@
 
 <dynamicConfig>
     <entry key="media_files_url">
-            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest-1.0.zip</value>
+            <value>https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest-2.0.zip</value>
     </entry>
 </dynamicConfig>
diff --git a/media/module/codecs/amrwb/enc/test/README.md b/media/module/codecs/amrwb/enc/test/README.md
index 3b9cc39..ea2c31e 100644
--- a/media/module/codecs/amrwb/enc/test/README.md
+++ b/media/module/codecs/amrwb/enc/test/README.md
@@ -22,7 +22,7 @@
 adb push ${OUT}/data/nativetest/AmrwbEncoderTest/AmrwbEncoderTest /data/local/tmp/
 ```
 
-The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest-1.0.zip). Download, unzip and push these files into device for testing.
+The resource file for the tests is taken from [here](https://dl.google.com/android-unittest/media/frameworks/av/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest-2.0.zip). Download, unzip and push these files into device for testing.
 
 ```
 adb push AmrwbEncoderTest-1.0 /data/local/tmp/
@@ -30,7 +30,7 @@
 
 usage: AmrwbEncoderTest -P \<path_to_folder\>
 ```
-adb shell /data/local/tmp/AmrwbEncoderTest -P /data/local/tmp/AmrwbEncoderTest-1.0/
+adb shell /data/local/tmp/AmrwbEncoderTest -P /data/local/tmp/AmrwbEncoderTest-2.0/
 ```
 Alternatively, the test can also be run using atest command.
 
diff --git a/media/module/codecserviceregistrant/Android.bp b/media/module/codecserviceregistrant/Android.bp
index becb98a..56cd8b8 100644
--- a/media/module/codecserviceregistrant/Android.bp
+++ b/media/module/codecserviceregistrant/Android.bp
@@ -55,6 +55,8 @@
         "com.android.media.swcodec",
     ],
 
+    export_include_dirs: ["include"],
+
     srcs: [
         "CodecServiceRegistrant.cpp",
     ],
diff --git a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
index 6df9dc8..433b5e9 100644
--- a/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
+++ b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
@@ -40,7 +40,7 @@
 #include <codec2/aidl/ComponentStore.h>
 #include <codec2/aidl/ParamTypes.h>
 
-#include <media/CodecServiceRegistrant.h>
+#include <codecserviceregistrant/CodecServiceRegistrant.h>
 
 namespace /* unnamed */ {
 
@@ -775,13 +775,12 @@
     return nullptr;
 }
 
-extern "C" void RegisterCodecServices() {
+/**
+ * This function encapsulates the core logic required to register codec services,
+ * separated from threadpool management to avoid timeouts when called by the fuzzer.
+ */
+static void RegisterCodecServicesWithExistingThreadpool() {
     const bool aidlSelected = c2_aidl::utils::IsSelected();
-    constexpr int kThreadCount = 64;
-    ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
-    ABinderProcess_startThreadPool();
-    ::android::hardware::configureRpcThreadpool(kThreadCount, false);
-
     LOG(INFO) << "Creating software Codec2 service...";
     std::shared_ptr<C2ComponentStore> store =
         android::GetCodec2PlatformComponentStore();
@@ -791,47 +790,6 @@
     }
 
     using namespace ::android::hardware::media::c2;
-
-    if (!ionPropertiesDefined()) {
-        using IComponentStore =
-            ::android::hardware::media::c2::V1_0::IComponentStore;
-        std::string const preferredStoreName = "default";
-        if (aidlSelected) {
-            std::shared_ptr<c2_aidl::IComponentStore> preferredStore;
-            if (__builtin_available(android __ANDROID_API_S__, *)) {
-                std::string instanceName = ::android::base::StringPrintf(
-                        "%s/%s", c2_aidl::IComponentStore::descriptor, preferredStoreName.c_str());
-                if (AServiceManager_isDeclared(instanceName.c_str())) {
-                    preferredStore = c2_aidl::IComponentStore::fromBinder(::ndk::SpAIBinder(
-                            AServiceManager_waitForService(instanceName.c_str())));
-                }
-            }
-            if (preferredStore) {
-                ::android::SetPreferredCodec2ComponentStore(
-                        std::make_shared<H2C2ComponentStore>(preferredStore));
-                LOG(INFO) <<
-                        "Preferred Codec2 AIDL store is set to \"" <<
-                        preferredStoreName << "\".";
-            } else {
-                LOG(INFO) <<
-                        "Preferred Codec2 AIDL store is defaulted to \"software\".";
-            }
-        } else {
-            sp<IComponentStore> preferredStore =
-                IComponentStore::getService(preferredStoreName.c_str());
-            if (preferredStore) {
-                ::android::SetPreferredCodec2ComponentStore(
-                        std::make_shared<H2C2ComponentStore>(preferredStore));
-                LOG(INFO) <<
-                        "Preferred Codec2 HIDL store is set to \"" <<
-                        preferredStoreName << "\".";
-            } else {
-                LOG(INFO) <<
-                        "Preferred Codec2 HIDL store is defaulted to \"software\".";
-            }
-        }
-    }
-
     bool registered = false;
     const std::string aidlServiceName =
         std::string(c2_aidl::IComponentStore::descriptor) + "/software";
@@ -877,11 +835,61 @@
                      " so it is not being registered with hwservicemanager.";
     }
 
+    // Preferred store must be set after the store is registered to ensure that
+    // the correct preferred store is set.
+    if (!ionPropertiesDefined()) {
+        using IComponentStore =
+            ::android::hardware::media::c2::V1_0::IComponentStore;
+        std::string const preferredStoreName = "default";
+        if (aidlSelected) {
+            std::shared_ptr<c2_aidl::IComponentStore> preferredStore;
+            if (__builtin_available(android __ANDROID_API_S__, *)) {
+                std::string instanceName = ::android::base::StringPrintf(
+                        "%s/%s", c2_aidl::IComponentStore::descriptor, preferredStoreName.c_str());
+                if (AServiceManager_isDeclared(instanceName.c_str())) {
+                    preferredStore = c2_aidl::IComponentStore::fromBinder(::ndk::SpAIBinder(
+                            AServiceManager_waitForService(instanceName.c_str())));
+                }
+            }
+            if (preferredStore) {
+                ::android::SetPreferredCodec2ComponentStore(
+                        std::make_shared<H2C2ComponentStore>(preferredStore));
+                LOG(INFO) <<
+                        "Preferred Codec2 AIDL store is set to \"" <<
+                        preferredStoreName << "\".";
+            } else {
+                LOG(INFO) <<
+                        "Preferred Codec2 AIDL store is defaulted to \"software\".";
+            }
+        } else {
+            sp<IComponentStore> preferredStore =
+                IComponentStore::getService(preferredStoreName.c_str());
+            if (preferredStore) {
+                ::android::SetPreferredCodec2ComponentStore(
+                        std::make_shared<H2C2ComponentStore>(preferredStore));
+                LOG(INFO) <<
+                        "Preferred Codec2 HIDL store is set to \"" <<
+                        preferredStoreName << "\".";
+            } else {
+                LOG(INFO) <<
+                        "Preferred Codec2 HIDL store is defaulted to \"software\".";
+            }
+        }
+    }
+
     if (registered) {
         LOG(INFO) << "Software Codec2 service created and registered.";
     }
+}
+
+extern "C" void RegisterCodecServices() {
+    constexpr int kThreadCount = 64;
+    ABinderProcess_setThreadPoolMaxThreadCount(kThreadCount);
+    ABinderProcess_startThreadPool();
+    ::android::hardware::configureRpcThreadpool(kThreadCount, false);
+
+    RegisterCodecServicesWithExistingThreadpool();
 
     ABinderProcess_joinThreadPool();
     ::android::hardware::joinRpcThreadpool();
 }
-
diff --git a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
index 4868e0c..0baf1ca 100644
--- a/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
+++ b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
@@ -13,6 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#include <codecserviceregistrant/CodecServiceRegistrant.h>
+
 #include "../CodecServiceRegistrant.cpp"
 #include "fuzzer/FuzzedDataProvider.h"
 #include <C2Config.h>
@@ -166,9 +169,9 @@
 void CodecServiceRegistrantFuzzer::process(const uint8_t *data, size_t size) {
   mFDP = new FuzzedDataProvider(data, size);
   invokeH2C2ComponentStore();
-  /** RegisterCodecServices is called here to improve code coverage */
-  /** as currently it is not called by codecServiceRegistrant       */
-  RegisterCodecServices();
+  /** RegisterCodecServicesWithExistingThreadpool() is called here to improve
+   * code coverage as currently it is not called in codecServiceRegistrant.cpp */
+  RegisterCodecServicesWithExistingThreadpool();
   delete mFDP;
 }
 
diff --git a/media/libmedia/include/media/CodecServiceRegistrant.h b/media/module/codecserviceregistrant/include/codecserviceregistrant/CodecServiceRegistrant.h
similarity index 77%
rename from media/libmedia/include/media/CodecServiceRegistrant.h
rename to media/module/codecserviceregistrant/include/codecserviceregistrant/CodecServiceRegistrant.h
index e0af781..1c6f71f 100644
--- a/media/libmedia/include/media/CodecServiceRegistrant.h
+++ b/media/module/codecserviceregistrant/include/codecserviceregistrant/CodecServiceRegistrant.h
@@ -18,6 +18,13 @@
 
 #define CODEC_SERVICE_REGISTRANT_H_
 
+/**
+ * This function starts the threadpool, calls the registration logic
+ * encapsulated in RegisterCodecServicesWithExistingThreadpool(), and
+ * then stops the threadpool.
+ */
+extern "C" void RegisterCodecServices();
+
 typedef void (*RegisterCodecServicesFunc)();
 
 #endif  // CODEC_SERVICE_REGISTRANT_H_
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index b3707c8..f247f8c 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -523,11 +523,10 @@
     }
 
     [this, &track] {
-        int64_t duration;
+        int64_t duration = track->mMdhdDurationUs;
         int32_t samplerate;
         // Only for audio track.
-        if (track->elst_needs_processing && mHeaderTimescale != 0 &&
-            AMediaFormat_getInt64(track->meta, AMEDIAFORMAT_KEY_DURATION, &duration) &&
+        if (track->elst_needs_processing && mHeaderTimescale != 0 && duration != 0 &&
             AMediaFormat_getInt32(track->meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &samplerate)) {
             // Elst has to be processed only the first time this function is called.
             track->elst_needs_processing = false;
@@ -1645,7 +1644,10 @@
                           (long long) duration, (long long) mLastTrack->timescale);
                     return ERROR_MALFORMED;
                 }
-                AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs);
+                // Store this track's mdhd duration to calculate the padding.
+                mLastTrack->mMdhdDurationUs = (int64_t)durationUs;
+            } else {
+                mLastTrack->mMdhdDurationUs = 0;
             }
 
             uint8_t lang[2];
@@ -3907,17 +3909,18 @@
     }
 
     int32_t id;
+    int64_t duration;
 
     if (version == 1) {
         // we can get ctime value from U64_AT(&buffer[4])
         // we can get mtime value from U64_AT(&buffer[12])
         id = U32_AT(&buffer[20]);
-        // we can get duration value from U64_AT(&buffer[28])
+        duration = U64_AT(&buffer[28]);
     } else if (version == 0) {
         // we can get ctime value from U32_AT(&buffer[4])
         // we can get mtime value from U32_AT(&buffer[8])
         id = U32_AT(&buffer[12]);
-        // we can get duration value from U32_AT(&buffer[20])
+        duration = U32_AT(&buffer[20]);
     } else {
         return ERROR_UNSUPPORTED;
     }
@@ -3926,6 +3929,15 @@
         return ERROR_MALFORMED;
 
     AMediaFormat_setInt32(mLastTrack->meta, AMEDIAFORMAT_KEY_TRACK_ID, id);
+    if (duration != 0 && mHeaderTimescale != 0) {
+        long double durationUs = ((long double)duration * 1000000) / mHeaderTimescale;
+        if (durationUs < 0 || durationUs > INT64_MAX) {
+            ALOGE("cannot represent %lld * 1000000 / %lld in 64 bits",
+                  (long long) duration, (long long) mHeaderTimescale);
+            return ERROR_MALFORMED;
+        }
+        AMediaFormat_setInt64(mLastTrack->meta, AMEDIAFORMAT_KEY_DURATION, durationUs);
+    }
 
     size_t matrixOffset = dynSize + 16;
     int32_t a00 = U32_AT(&buffer[matrixOffset]);
diff --git a/media/module/extractors/mp4/include/MPEG4Extractor.h b/media/module/extractors/mp4/include/MPEG4Extractor.h
index 542a3e6..59626f6 100644
--- a/media/module/extractors/mp4/include/MPEG4Extractor.h
+++ b/media/module/extractors/mp4/include/MPEG4Extractor.h
@@ -96,7 +96,7 @@
 
         uint8_t *mTx3gBuffer;
         size_t mTx3gSize, mTx3gFilled;
-
+        int64_t mMdhdDurationUs;
 
         Track() {
             next = NULL;
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 3d873df..b250a03 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -52,9 +52,6 @@
     symbol_file: "libmediandk.map.txt",
     first_version: "21",
     unversioned_until: "current",
-    export_header_libs: [
-        "libmediandk_headers",
-    ],
 }
 
 ndk_headers {
diff --git a/media/tests/benchmark/MediaBenchmarkTest/Android.bp b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
index d41a7f9..1049d5e 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/Android.bp
+++ b/media/tests/benchmark/MediaBenchmarkTest/Android.bp
@@ -36,8 +36,8 @@
     resource_dirs: ["res"],
 
     libs: [
-        "android.test.runner",
-        "android.test.base",
+        "android.test.runner.stubs.system",
+        "android.test.base.stubs.system",
     ],
 
     jni_libs: [
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index ec68de7..6a5bbbe 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -23,6 +23,7 @@
 #include <android-base/logging.h>
 #include <android-base/strings.h>
 #include <audio_utils/clock.h>
+#include <cutils/properties.h>
 #include <mediautils/EventLog.h>
 #include <mediautils/FixedString.h>
 #include <mediautils/MethodStatistics.h>
@@ -36,6 +37,46 @@
 
 
 namespace android::mediautils {
+
+// Note: The sum of kDefaultTimeOutDurationMs and kDefaultSecondChanceDurationMs
+// should be no less than 2 seconds, otherwise spurious timeouts
+// may occur with system suspend.
+static constexpr int kDefaultTimeoutDurationMs = 3000;
+
+// Due to suspend abort not incrementing the monotonic clock,
+// we allow another second chance timeout after the first timeout expires.
+//
+// The total timeout is therefore kDefaultTimeoutDuration + kDefaultSecondChanceDuration,
+// and the result is more stable when the monotonic clock increments during suspend.
+//
+static constexpr int kDefaultSecondChanceDurationMs = 2000;
+
+/* static */
+TimeCheck::Duration TimeCheck::getDefaultTimeoutDuration() {
+    static constinit std::atomic<int> defaultTimeoutDurationMs{};
+    auto defaultMs = defaultTimeoutDurationMs.load(std::memory_order_relaxed);
+    if (defaultMs == 0) {
+        defaultMs = property_get_int32(
+                "audio.timecheck.timeout_duration_ms", kDefaultTimeoutDurationMs);
+        if (defaultMs < 1) defaultMs = kDefaultTimeoutDurationMs;
+        defaultTimeoutDurationMs.store(defaultMs, std::memory_order_relaxed);
+    }
+    return std::chrono::milliseconds(defaultMs);
+}
+
+/* static */
+TimeCheck::Duration TimeCheck::getDefaultSecondChanceDuration() {
+    static constinit std::atomic<int> defaultSecondChanceDurationMs{};
+    auto defaultMs = defaultSecondChanceDurationMs.load(std::memory_order_relaxed);
+    if (defaultMs == 0) {
+        defaultMs = property_get_int32(
+                "audio.timecheck.second_chance_duration_ms", kDefaultSecondChanceDurationMs);
+        if (defaultMs < 1) defaultMs = kDefaultSecondChanceDurationMs;
+        defaultSecondChanceDurationMs.store(defaultMs, std::memory_order_relaxed);
+    }
+    return std::chrono::milliseconds(defaultMs);
+}
+
 // This function appropriately signals a pid to dump a backtrace if we are
 // running on device (and the HAL exists). If we are not running on an Android
 // device, there is no HAL to signal (so we do nothing).
@@ -143,6 +184,22 @@
 }
 
 /* static */
+std::string TimeCheck::signalAudioHals() {
+    std::vector<pid_t> pids = getAudioHalPids();
+    std::string halPids;
+    if (pids.size() != 0) {
+        for (const auto& pid : pids) {
+            ALOGI("requesting tombstone for pid: %d", pid);
+            halPids.append(std::to_string(pid)).append(" ");
+            signalAudioHAL(pid);
+        }
+        // Allow time to complete, usually the caller is forcing restart afterwards.
+        sleep(1);
+    }
+    return halPids;
+}
+
+/* static */
 TimerThread& TimeCheck::getTimeCheckThread() {
     static TimerThread sTimeCheckThread{};
     return sTimeCheckThread;
@@ -182,23 +239,25 @@
 
 /* static */
 std::string TimeCheck::analyzeTimeouts(
-        float requestedTimeoutMs, float elapsedSteadyMs, float elapsedSystemMs) {
+        float requestedTimeoutMs, float secondChanceMs,
+        float elapsedSteadyMs, float elapsedSystemMs) {
     // Track any OS clock issues with suspend.
     // It is possible that the elapsedSystemMs is much greater than elapsedSteadyMs if
     // a suspend occurs; however, we always expect the timeout ms should always be slightly
     // less than the elapsed steady ms regardless of whether a suspend occurs or not.
 
-    std::string s("Timeout ms ");
-    s.append(std::to_string(requestedTimeoutMs))
-        .append(" elapsed steady ms ").append(std::to_string(elapsedSteadyMs))
-        .append(" elapsed system ms ").append(std::to_string(elapsedSystemMs));
+    const float totalTimeoutMs = requestedTimeoutMs + secondChanceMs;
+    std::string s = std::format(
+            "Timeout ms {:.2f} ({:.2f} + {:.2f})"
+            " elapsed steady ms {:.4f} elapsed system ms {:.4f}",
+            totalTimeoutMs, requestedTimeoutMs, secondChanceMs, elapsedSteadyMs, elapsedSystemMs);
 
     // Is there something unusual?
     static constexpr float TOLERANCE_CONTEXT_SWITCH_MS = 200.f;
 
-    if (requestedTimeoutMs > elapsedSteadyMs || requestedTimeoutMs > elapsedSystemMs) {
+    if (totalTimeoutMs > elapsedSteadyMs || totalTimeoutMs > elapsedSystemMs) {
         s.append("\nError: early expiration - "
-                "requestedTimeoutMs should be less than elapsed time");
+                "totalTimeoutMs should be less than elapsed time");
     }
 
     if (elapsedSteadyMs > elapsedSystemMs + TOLERANCE_CONTEXT_SWITCH_MS) {
@@ -206,13 +265,13 @@
     }
 
     // This has been found in suspend stress testing.
-    if (elapsedSteadyMs > requestedTimeoutMs + TOLERANCE_CONTEXT_SWITCH_MS) {
+    if (elapsedSteadyMs > totalTimeoutMs + TOLERANCE_CONTEXT_SWITCH_MS) {
         s.append("\nWarning: steady time significantly exceeds timeout "
                 "- possible thread stall or aborted suspend");
     }
 
     // This has been found in suspend stress testing.
-    if (elapsedSystemMs > requestedTimeoutMs + TOLERANCE_CONTEXT_SWITCH_MS) {
+    if (elapsedSystemMs > totalTimeoutMs + TOLERANCE_CONTEXT_SWITCH_MS) {
         s.append("\nInformation: system time significantly exceeds timeout "
                 "- possible suspend");
     }
@@ -259,21 +318,14 @@
     // HAL processes which can affect thread behavior.
     const auto snapshotAnalysis = getTimeCheckThread().getSnapshotAnalysis(4 /* retiredCount */);
 
-    // Generate audio HAL processes tombstones and allow time to complete
-    // before forcing restart
-    std::vector<pid_t> pids = TimeCheck::getAudioHalPids();
-    std::string halPids = "HAL pids [ ";
-    if (pids.size() != 0) {
-        for (const auto& pid : pids) {
-            ALOGI("requesting tombstone for pid: %d", pid);
-            halPids.append(std::to_string(pid)).append(" ");
-            signalAudioHAL(pid);
-        }
-        sleep(1);
+    // Generate audio HAL processes tombstones.
+    std::string halPids = signalAudioHals();
+    if (!halPids.empty()) {
+        halPids = "HAL pids [ " + halPids + "]";
     } else {
-        ALOGI("No HAL process pid available, skipping tombstones");
+        halPids = "No HAL process pids available";
+        ALOGI("%s", (halPids + ", skipping tombstones").c_str());
     }
-    halPids.append("]");
 
     LOG_EVENT_STRING(LOGTAG_AUDIO_BINDER_TIMEOUT, tag.c_str());
 
@@ -282,7 +334,7 @@
             .append(tag)
             .append(" scheduled ").append(formatTime(startSystemTime))
             .append(" on thread ").append(std::to_string(tid)).append("\n")
-            .append(analyzeTimeouts(requestedTimeoutMs + secondChanceMs,
+            .append(analyzeTimeouts(requestedTimeoutMs, secondChanceMs,
                     elapsedSteadyMs, elapsedSystemMs)).append("\n")
             .append(halPids).append("\n")
             .append(snapshotAnalysis.toString());
diff --git a/media/utils/include/mediautils/TimeCheck.h b/media/utils/include/mediautils/TimeCheck.h
index f1d572f..c112863 100644
--- a/media/utils/include/mediautils/TimeCheck.h
+++ b/media/utils/include/mediautils/TimeCheck.h
@@ -42,19 +42,29 @@
     //  float elapsedMs (the elapsed time to this event).
     using OnTimerFunc = std::function<void(bool /* timeout */, float /* elapsedMs */ )>;
 
-    // The default timeout is chosen to be less than system server watchdog timeout
-    // Note: kDefaultTimeOutMs should be no less than 2 seconds, otherwise spurious timeouts
-    // may occur with system suspend.
-    static constexpr TimeCheck::Duration kDefaultTimeoutDuration = std::chrono::milliseconds(3000);
+    /**
+     * Returns the default timeout to use for TimeCheck.
+     *
+     * The default timeout of 3000ms (kDefaultTimeoutDurationMs) is chosen to be less than
+     * the system server watchdog timeout, and can be changed by the sysprop
+     * audio.timecheck.timeout_duration_ms.
+     * A second chance wait may be set to extend the check.
+     */
+    static TimeCheck::Duration getDefaultTimeoutDuration();
 
-    // Due to suspend abort not incrementing the monotonic clock,
-    // we allow another second chance timeout after the first timeout expires.
-    //
-    // The total timeout is therefore kDefaultTimeoutDuration + kDefaultSecondChanceDuration,
-    // and the result is more stable when the monotonic clock increments during suspend.
-    //
-    static constexpr TimeCheck::Duration kDefaultSecondChanceDuration =
-            std::chrono::milliseconds(2000);
+    /**
+     * Returns the second chance timeout to use for TimeCheck.
+     *
+     * Due to suspend abort not incrementing the monotonic clock,
+     * we allow another second chance timeout after the first timeout expires.
+     * The second chance timeout default of 2000ms (kDefaultSecondChanceDurationMs)
+     * may be changed by the sysprop audio.timecheck.second_chance_duration_ms.
+     *
+     * The total timeout is therefore
+     * getDefaultTimeoutDuration() + getDefaultSecondChanceDuration(),
+     * and the result is more stable when the monotonic clock increments during suspend.
+     */
+    static TimeCheck::Duration getDefaultSecondChanceDuration();
 
     /**
      * TimeCheck is a RAII object which will notify a callback
@@ -97,6 +107,7 @@
     static std::string toString();
     static void setAudioHalPids(const std::vector<pid_t>& pids);
     static std::vector<pid_t> getAudioHalPids();
+    static std::string signalAudioHals();
 
   private:
     // Helper class for handling events.
@@ -130,7 +141,8 @@
     // Returns a string that represents the timeout vs elapsed time,
     // and diagnostics if there are any potential issues.
     static std::string analyzeTimeouts(
-            float timeoutMs, float elapsedSteadyMs, float elapsedSystemMs);
+            float timeoutMs, float secondChanceMs,
+            float elapsedSteadyMs, float elapsedSystemMs);
 
     static TimerThread& getTimeCheckThread();
     static void accessAudioHalPids(std::vector<pid_t>* pids, bool update);
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index b763f09..bf2915a 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -141,9 +141,15 @@
 cc_defaults {
     name: "libaudioflinger_dependencies",
 
+    header_libs: [
+        "libaudiohal_headers", // required for AudioFlinger
+    ],
+
     shared_libs: [
+        "audio-permission-aidl-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
+        "audiopermissioncontroller",
         "av-types-aidl-cpp",
         "com.android.media.audio-aconfig-cc",
         "effect-aidl-cpp",
@@ -177,11 +183,6 @@
         "libvibrator",
         "packagemanager_aidl-cpp",
     ],
-
-    static_libs: [
-        "libaudiospdif",
-        "libmedialogservice",
-    ],
 }
 
 cc_library {
@@ -213,22 +214,21 @@
     ],
 
     static_libs: [
+        "libaudiospdif",
         "libcpustats",
-        "libpermission",
+        "libmedialogservice",
     ],
 
     header_libs: [
-        "audiopermissioncontroller_headers",
         "audiopolicyservicelocal_headers",
         "libaaudio_headers",
-        "libaudioclient_headers",
-        "libaudiohal_headers",
-        "libaudioutils_headers",
         "libmedia_headers",
     ],
 
     export_header_lib_headers: ["audiopolicyservicelocal_headers"],
 
+    export_include_dirs: ["."],
+
     export_shared_lib_headers: [
         "libpermission",
     ],
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index a17ac58..537a097 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2923,7 +2923,8 @@
                                                         audio_config_base_t *mixerConfig,
                                                         audio_devices_t deviceType,
                                                         const String8& address,
-                                                        audio_output_flags_t flags)
+                                                        audio_output_flags_t flags,
+                                                        const audio_attributes_t attributes)
 {
     AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
     if (outHwDev == NULL) {
@@ -2941,13 +2942,18 @@
 
     mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
     AudioStreamOut *outputStream = NULL;
+
+    playback_track_metadata_v7_t trackMetadata;
+    trackMetadata.base.usage = attributes.usage;
+
     status_t status = outHwDev->openOutputStream(
             &outputStream,
             *output,
             deviceType,
             flags,
             halConfig,
-            address.c_str());
+            address.c_str(),
+            {trackMetadata});
 
     mHardwareStatus = AUDIO_HW_IDLE;
 
@@ -3016,6 +3022,8 @@
             aidl2legacy_DeviceDescriptorBase(request.device));
     audio_output_flags_t flags = VALUE_OR_RETURN_STATUS(
             aidl2legacy_int32_t_audio_output_flags_t_mask(request.flags));
+    audio_attributes_t attributes = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioAttributes_audio_attributes_t(request.attributes));
 
     audio_io_handle_t output;
 
@@ -3038,7 +3046,7 @@
     audio_utils::lock_guard _l(mutex());
 
     const sp<IAfThreadBase> thread = openOutput_l(module, &output, &halConfig,
-            &mixerConfig, deviceType, address, flags);
+            &mixerConfig, deviceType, address, flags, attributes);
     if (thread != 0) {
         uint32_t latencyMs = 0;
         if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
@@ -3940,8 +3948,12 @@
         // TODO: We could check compatibility of the secondaryThread with the PatchTrack
         // for fast usage: thread has fast mixer, sample rate matches, etc.;
         // for now, we exclude fast tracks by removing the Fast flag.
+        constexpr audio_output_flags_t kIncompatiblePatchTrackFlags =
+                static_cast<audio_output_flags_t>(AUDIO_OUTPUT_FLAG_FAST
+                        | AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
+
         const audio_output_flags_t outputFlags =
-                (audio_output_flags_t)(track->getOutputFlags() & ~AUDIO_OUTPUT_FLAG_FAST);
+                (audio_output_flags_t)(track->getOutputFlags() & ~kIncompatiblePatchTrackFlags);
         sp<IAfPatchTrack> patchTrack = IAfPatchTrack::create(secondaryThread,
                                                        track->streamType(),
                                                        track->sampleRate(),
@@ -4491,7 +4503,7 @@
             // TODO(b/184194057): Use the vibrator information from the vibrator that will be used
             // for the HapticGenerator.
             const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
-                    std::move(getDefaultVibratorInfo_l());
+                    getDefaultVibratorInfo_l();
             if (defaultVibratorInfo) {
                 // Only set the vibrator info when it is a valid one.
                 audio_utils::lock_guard _cl(chain->mutex());
@@ -5126,8 +5138,8 @@
         } else {
             getIAudioFlingerStatistics().event(code, elapsedMs);
         }
-    }, mediautils::TimeCheck::kDefaultTimeoutDuration,
-    mediautils::TimeCheck::kDefaultSecondChanceDuration,
+    }, mediautils::TimeCheck::getDefaultTimeoutDuration(),
+    mediautils::TimeCheck::getDefaultSecondChanceDuration(),
     true /* crashOnTimeout */);
 
     return delegate();
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 501aed1..21c171d 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -337,9 +337,12 @@
             audio_config_base_t* mixerConfig,
             audio_devices_t deviceType,
             const String8& address,
-            audio_output_flags_t flags) final REQUIRES(mutex());
+            audio_output_flags_t flags,
+            audio_attributes_t attributes) final REQUIRES(mutex());
     const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
-            getAudioHwDevs_l() const final REQUIRES(mutex()) { return mAudioHwDevs; }
+            getAudioHwDevs_l() const final REQUIRES(mutex(), hardwareMutex()) {
+              return mAudioHwDevs;
+            }
     void updateDownStreamPatches_l(const struct audio_patch* patch,
             const std::set<audio_io_handle_t>& streams) final REQUIRES(mutex());
     void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index feae97e..7cb9329 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -71,10 +71,15 @@
 
 void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
     ALOGV("%s", __func__);
+    // Keep a reference on disconnected handle to delay destruction without lock held.
+    std::vector<sp<IAfEffectHandle>> disconnectedHandles{};
     audio_utils::lock_guard _l(mutex());
     for (auto& effectProxies : mDeviceEffects) {
         for (auto& effect : effectProxies.second) {
-            effect->onReleasePatch(handle);
+            sp<IAfEffectHandle> disconnectedHandle = effect->onReleasePatch(handle);
+            if (disconnectedHandle != nullptr) {
+                disconnectedHandles.push_back(std::move(disconnectedHandle));
+            }
         }
     }
 }
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 4da498b..cfd0a5e 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1760,6 +1760,9 @@
         const sp<media::IEffectClient>& effectClient,
         int32_t priority, bool notifyFramesProcessed)
 {
+    if (client == nullptr && effectClient == nullptr) {
+        return sp<InternalEffectHandle>::make(effect, notifyFramesProcessed);
+    }
     return sp<EffectHandle>::make(
             effect, client, effectClient, priority, notifyFramesProcessed);
 }
@@ -1767,12 +1770,14 @@
 EffectHandle::EffectHandle(const sp<IAfEffectBase>& effect,
                                          const sp<Client>& client,
                                          const sp<media::IEffectClient>& effectClient,
-                                         int32_t priority, bool notifyFramesProcessed)
-    : BnEffect(),
+                                         int32_t priority, bool notifyFramesProcessed,
+                                         bool isInternal,
+                                         audio_utils::MutexOrder mutexOrder)
+    : BnEffect(), mMutex(audio_utils::mutex{mutexOrder}),
     mEffect(effect), mEffectClient(media::EffectClientAsyncProxy::makeIfNeeded(effectClient)),
     mClient(client), mCblk(nullptr),
     mPriority(priority), mHasControl(false), mEnabled(false), mDisconnected(false),
-    mNotifyFramesProcessed(notifyFramesProcessed)
+    mNotifyFramesProcessed(notifyFramesProcessed), mIsInternal(isInternal)
 {
     ALOGV("constructor %p client %p", this, client.get());
     setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
@@ -1939,7 +1944,7 @@
 
 void EffectHandle::disconnect(bool unpinIfLast)
 {
-    audio_utils::lock_guard _l(mutex());
+    audio_utils::unique_lock _l(mutex());
     ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
     if (mDisconnected) {
         if (unpinIfLast) {
@@ -1951,11 +1956,19 @@
     {
         sp<IAfEffectBase> effect = mEffect.promote();
         if (effect != 0) {
+            // Unlock e.g. for device effect: may need to acquire AudioFlinger lock
+            // Also Internal Effect Handle would require Proxy lock (and vice versa).
+            if (isInternal()) {
+                _l.unlock();
+            }
             if (effect->disconnectHandle(this, unpinIfLast) > 0) {
                 ALOGW("%s Effect handle %p disconnected after thread destruction",
                     __func__, this);
             }
             effect->updatePolicyState();
+            if (isInternal()) {
+                _l.lock();
+            }
         }
     }
 
@@ -3544,8 +3557,7 @@
                 mHalEffect->setDevices({mDevice});
             }
         }
-        *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/,
-                                   mNotifyFramesProcessed);
+        *handle = new InternalEffectHandle(mHalEffect, mNotifyFramesProcessed);
         status = (*handle)->initCheck();
         if (status == OK) {
             status = mHalEffect->addHandle((*handle).get());
@@ -3592,15 +3604,16 @@
     return status;
 }
 
-void DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
-    sp<IAfEffectHandle> effect;
+sp<IAfEffectHandle> DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
+    sp<IAfEffectHandle> disconnectedHandle;
     {
         audio_utils::lock_guard _l(proxyMutex());
         if (mEffectHandles.find(patchHandle) != mEffectHandles.end()) {
-            effect = mEffectHandles.at(patchHandle);
+            disconnectedHandle = std::move(mEffectHandles.at(patchHandle));
             mEffectHandles.erase(patchHandle);
         }
     }
+    return disconnectedHandle;
 }
 
 
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 5c90176..9ecf89e 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -344,7 +344,8 @@
     EffectHandle(const sp<IAfEffectBase>& effect,
             const sp<Client>& client,
             const sp<media::IEffectClient>& effectClient,
-            int32_t priority, bool notifyFramesProcessed);
+            int32_t priority, bool notifyFramesProcessed, bool isInternal = false,
+            audio_utils::MutexOrder mutexOrder = audio_utils::MutexOrder::kEffectHandle_Mutex);
     ~EffectHandle() override;
     status_t onTransact(
             uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) final;
@@ -364,6 +365,11 @@
                                       int32_t* _aidl_return) final;
 
     const sp<Client>& client() const final { return mClient; }
+    /**
+     * Checks if the handle is internal, aka created by AudioFlinger for internal needs (e.g.
+     * device effect HAL handle or device effect thread handle).
+     */
+    virtual bool isInternal() const { return mIsInternal; }
 
     sp<android::media::IEffect> asIEffect() final {
         return sp<android::media::IEffect>::fromExisting(this);
@@ -401,15 +407,18 @@
 
     void dumpToBuffer(char* buffer, size_t size) const final;
 
+protected:
+    // protects IEffect method calls
+    mutable audio_utils::mutex mMutex;
 
 private:
     DISALLOW_COPY_AND_ASSIGN(EffectHandle);
 
-    audio_utils::mutex& mutex() const RETURN_CAPABILITY(android::audio_utils::EffectHandle_Mutex) {
+    virtual audio_utils::mutex& mutex() const
+            RETURN_CAPABILITY(android::audio_utils::EffectHandle_Mutex) {
         return mMutex;
     }
-    // protects IEffect method calls
-    mutable audio_utils::mutex mMutex{audio_utils::MutexOrder::kEffectHandle_Mutex};
+
     const wp<IAfEffectBase> mEffect;               // pointer to controlled EffectModule
     const sp<media::IEffectClient> mEffectClient;  // callback interface for client notifications
     /*const*/ sp<Client> mClient;            // client for shared memory allocation, see
@@ -425,6 +434,28 @@
     bool mDisconnected;                      // Set to true by disconnect()
     const bool mNotifyFramesProcessed;       // true if the client callback event
                                              // EVENT_FRAMES_PROCESSED must be generated
+    const bool mIsInternal;
+};
+
+/**
+ * There are 2 types of effects:
+ * -Session Effect: handle is directly called from the client, without AudioFlinger lock.
+ * -Device Effect: a device effect proxy is aggregating a collection of internal effect handles that
+ * controls the same effect added on all audio patches involving the device effect selected port
+ * requested either by a client or by AudioPolicyEffects. These internal effect handles do not have
+ * client. Sequence flow implies a different locking order, hence the lock is specialied.
+ */
+class InternalEffectHandle : public EffectHandle {
+public:
+    InternalEffectHandle(const sp<IAfEffectBase>& effect, bool notifyFramesProcessed) :
+            EffectHandle(effect, /* client= */ nullptr, /* effectClient= */ nullptr,
+                         /* priority= */ 0, notifyFramesProcessed, /* isInternal */ true,
+                         audio_utils::MutexOrder::kDeviceEffectHandle_Mutex) {}
+
+    virtual audio_utils::mutex& mutex() const
+            RETURN_CAPABILITY(android::audio_utils::DeviceEffectHandle_Mutex) {
+        return mMutex;
+    }
 };
 
 // the EffectChain class represents a group of effects associated to one audio session.
@@ -762,7 +793,7 @@
     status_t onUpdatePatch(audio_patch_handle_t oldPatchHandle, audio_patch_handle_t newPatchHandle,
            const IAfPatchPanel::Patch& patch) final;
 
-    void onReleasePatch(audio_patch_handle_t patchHandle) final;
+    sp<IAfEffectHandle> onReleasePatch(audio_patch_handle_t patchHandle) final;
 
     size_t removeEffect(const sp<IAfEffectModule>& effect) final;
 
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
index f1edcfe..3452e94 100644
--- a/services/audioflinger/IAfEffect.h
+++ b/services/audioflinger/IAfEffect.h
@@ -400,7 +400,14 @@
     virtual status_t onUpdatePatch(audio_patch_handle_t oldPatchHandle,
             audio_patch_handle_t newPatchHandle,
             const IAfPatchPanel::Patch& patch) = 0;
-    virtual void onReleasePatch(audio_patch_handle_t patchHandle) = 0;
+    /**
+     * Checks (and release) of the effect handle is linked with the given release patch handle.
+     *
+     * @param patchHandle handle of the released patch
+     * @return a reference on the effect handle released if any, nullptr otherwise.
+     * It allows to delay the destruction of the handle.
+     */
+    virtual sp<IAfEffectHandle> onReleasePatch(audio_patch_handle_t patchHandle) = 0;
 
     virtual void dump2(int fd, int spaces) const = 0; // TODO(b/291319101) naming?
 
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
index 6110e4c..37dce3a 100644
--- a/services/audioflinger/IAfPatchPanel.h
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -82,7 +82,8 @@
             audio_config_base_t* mixerConfig,
             audio_devices_t deviceType,
             const String8& address,
-            audio_output_flags_t flags) REQUIRES(mutex()) = 0;
+            audio_output_flags_t flags,
+            audio_attributes_t attributes) REQUIRES(mutex()) = 0;
     virtual audio_utils::mutex& mutex() const
             RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
     virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index f57470f..35f17c1 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -260,6 +260,7 @@
                     if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) {
                         flags = patch->sinks[0].flags.output;
                     }
+                    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
                     const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openOutput_l(
                                                             patch->sinks[0].ext.device.hw_module,
                                                             &output,
@@ -267,7 +268,8 @@
                                                             &mixerConfig,
                                                             outputDevice,
                                                             outputDeviceAddress,
-                                                            flags);
+                                                            flags,
+                                                            attributes);
                     ALOGV("mAfPatchPanelCallback->openOutput_l() returned %p", thread.get());
                     if (thread == 0) {
                         status = NO_MEMORY;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5c0ca5e..ecbd0ae 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1696,7 +1696,7 @@
             // TODO(b/184194057): Use the vibrator information from the vibrator that will be used
             // for the HapticGenerator.
             const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
-                    std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
+                    mAfThreadCallback->getDefaultVibratorInfo_l();
             if (defaultVibratorInfo) {
                 audio_utils::lock_guard _cl(chain->mutex());
                 // Only set the vibrator info when it is a valid one.
@@ -2917,7 +2917,7 @@
                 // TODO(b/184194780): Use the vibrator information from the vibrator that will be
                 // used to play this track.
                  audio_utils::lock_guard _l(mAfThreadCallback->mutex());
-                vibratorInfo = std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
+                vibratorInfo = mAfThreadCallback->getDefaultVibratorInfo_l();
             }
             mutex().lock();
             track->setHapticScale(hapticScale);
@@ -5093,7 +5093,6 @@
         // mPipeSink below
         // mNormalSink below
 {
-    setMasterBalance(afThreadCallback->getMasterBalance_l());
     ALOGV("MixerThread() id=%d type=%d", id, type);
     ALOGV("mSampleRate=%u, mChannelMask=%#x, mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
             "mFrameCount=%zu, mNormalFrameCount=%zu",
@@ -5105,6 +5104,8 @@
         // The Duplicating thread uses the AudioMixer and delivers data to OutputTracks
         // (downstream MixerThreads) in DuplicatingThread::threadLoop_write().
         // Do not create or use mFastMixer, mOutputSink, mPipeSink, or mNormalSink.
+        // Balance is *not* set in the DuplicatingThread here (or from AudioFlinger),
+        // as the downstream MixerThreads implement it.
         return;
     }
     // create an NBAIO sink for the HAL output stream, and negotiate
@@ -5264,6 +5265,9 @@
         mNormalSink = initFastMixer ? mPipeSink : mOutputSink;
         break;
     }
+    // setMasterBalance needs to be called after the FastMixer
+    // (if any) is set up, in order to deliver the balance settings to it.
+    setMasterBalance(afThreadCallback->getMasterBalance_l());
 }
 
 MixerThread::~MixerThread()
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 654b841..10a77ef 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -379,10 +379,10 @@
         return isOutput() ? outDeviceTypes_l() : DeviceTypeSet({inDeviceType_l()});
     }
 
-    const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const final {
+    const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const final REQUIRES(mutex()) {
         return mOutDeviceTypeAddrs;
     }
-    const AudioDeviceTypeAddr& inDeviceTypeAddr() const final {
+    const AudioDeviceTypeAddr& inDeviceTypeAddr() const final REQUIRES(mutex()) {
         return mInDeviceTypeAddr;
     }
 
diff --git a/services/audioflinger/datapath/AudioHwDevice.cpp b/services/audioflinger/datapath/AudioHwDevice.cpp
index 95e9ecc..5314e9e 100644
--- a/services/audioflinger/datapath/AudioHwDevice.cpp
+++ b/services/audioflinger/datapath/AudioHwDevice.cpp
@@ -43,7 +43,8 @@
         audio_devices_t deviceType,
         audio_output_flags_t flags,
         struct audio_config *config,
-        const char *address)
+        const char *address,
+        const std::vector<playback_track_metadata_v7_t>& sourceMetadata)
 {
 
     struct audio_config originalConfig = *config;
@@ -52,7 +53,7 @@
     // Try to open the HAL first using the current format.
     ALOGV("openOutputStream(), try sampleRate %d, format %#x, channelMask %#x", config->sample_rate,
             config->format, config->channel_mask);
-    status_t status = outputStream->open(handle, deviceType, config, address);
+    status_t status = outputStream->open(handle, deviceType, config, address, sourceMetadata);
 
     if (status != NO_ERROR) {
         delete outputStream;
@@ -72,7 +73,8 @@
         if (wrapperNeeded) {
             if (SPDIFEncoder::isFormatSupported(originalConfig.format)) {
                 outputStream = new SpdifStreamOut(this, flags, originalConfig.format);
-                status = outputStream->open(handle, deviceType, &originalConfig, address);
+                status = outputStream->open(handle, deviceType, &originalConfig, address,
+                                            sourceMetadata);
                 if (status != NO_ERROR) {
                     ALOGE("ERROR - openOutputStream(), SPDIF open returned %d",
                         status);
diff --git a/services/audioflinger/datapath/AudioHwDevice.h b/services/audioflinger/datapath/AudioHwDevice.h
index 80c1473..e1a9018 100644
--- a/services/audioflinger/datapath/AudioHwDevice.h
+++ b/services/audioflinger/datapath/AudioHwDevice.h
@@ -87,7 +87,8 @@
             audio_devices_t deviceType,
             audio_output_flags_t flags,
             struct audio_config *config,
-            const char *address);
+            const char *address,
+            const std::vector<playback_track_metadata_v7_t>& sourceMetadata);
 
     status_t openInputStream(
             AudioStreamIn **ppStreamIn,
diff --git a/services/audioflinger/datapath/AudioStreamOut.cpp b/services/audioflinger/datapath/AudioStreamOut.cpp
index a686ff6..c65373e 100644
--- a/services/audioflinger/datapath/AudioStreamOut.cpp
+++ b/services/audioflinger/datapath/AudioStreamOut.cpp
@@ -93,7 +93,8 @@
         audio_io_handle_t handle,
         audio_devices_t deviceType,
         struct audio_config *config,
-        const char *address)
+        const char *address,
+        const std::vector<playback_track_metadata_v7_t>& sourceMetadata)
 {
     sp<StreamOutHalInterface> outStream;
 
@@ -107,7 +108,8 @@
             customFlags,
             config,
             address,
-            &outStream);
+            &outStream,
+            sourceMetadata);
     ALOGV("AudioStreamOut::open(), HAL returned stream %p, sampleRate %d, format %#x,"
             " channelMask %#x, status %d", outStream.get(), config->sample_rate, config->format,
             config->channel_mask, status);
@@ -124,7 +126,8 @@
                 customFlags,
                 &customConfig,
                 address,
-                &outStream);
+                &outStream,
+                sourceMetadata);
         ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status);
     }
 
diff --git a/services/audioflinger/datapath/AudioStreamOut.h b/services/audioflinger/datapath/AudioStreamOut.h
index 2c9fb3e..2bf94a1 100644
--- a/services/audioflinger/datapath/AudioStreamOut.h
+++ b/services/audioflinger/datapath/AudioStreamOut.h
@@ -47,7 +47,8 @@
             audio_io_handle_t handle,
             audio_devices_t deviceType,
             struct audio_config *config,
-            const char *address);
+            const char *address,
+            const std::vector<playback_track_metadata_v7_t>& sourceMetadata);
 
     virtual ~AudioStreamOut();
 
diff --git a/services/audioflinger/datapath/SpdifStreamOut.cpp b/services/audioflinger/datapath/SpdifStreamOut.cpp
index 65a4eec..d3983b0 100644
--- a/services/audioflinger/datapath/SpdifStreamOut.cpp
+++ b/services/audioflinger/datapath/SpdifStreamOut.cpp
@@ -45,7 +45,8 @@
         audio_io_handle_t handle,
         audio_devices_t devices,
         struct audio_config *config,
-        const char *address)
+        const char *address,
+        const std::vector<playback_track_metadata_v7_t>& sourceMetadata)
 {
     struct audio_config customConfig = *config;
 
@@ -75,7 +76,8 @@
             handle,
             devices,
             &customConfig,
-            address);
+            address,
+            sourceMetadata);
 
     ALOGI("SpdifStreamOut::open() status = %d", status);
 
diff --git a/services/audioflinger/datapath/SpdifStreamOut.h b/services/audioflinger/datapath/SpdifStreamOut.h
index c6d27ba..1cd8f65 100644
--- a/services/audioflinger/datapath/SpdifStreamOut.h
+++ b/services/audioflinger/datapath/SpdifStreamOut.h
@@ -43,7 +43,8 @@
             audio_io_handle_t handle,
             audio_devices_t devices,
             struct audio_config *config,
-            const char *address) override;
+            const char *address,
+            const std::vector<playback_track_metadata_v7_t>& sourceMetadata) override;
 
     /**
     * Write audio buffer to driver. Returns number of bytes written, or a
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index e91e2a3..1bac259 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -294,8 +294,7 @@
     virtual status_t startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId,
-                                      uid_t uid,
-                                      bool internal = false) = 0;
+                                      uid_t uid) = 0;
     virtual status_t stopAudioSource(audio_port_handle_t portId) = 0;
 
     virtual status_t setMasterMono(bool mono) = 0;
@@ -478,7 +477,8 @@
                                 audio_config_base_t *mixerConfig,
                                 const sp<DeviceDescriptorBase>& device,
                                 uint32_t *latencyMs,
-                                audio_output_flags_t flags) = 0;
+                                audio_output_flags_t flags,
+                                audio_attributes_t audioAttributes) = 0;
     // creates a special output that is duplicated to the two outputs passed as arguments.
     // The duplication is performed by a special mixer thread in the AudioFlinger.
     virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index ee6af4c..3b7cae3 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -26,6 +26,25 @@
 
 using StreamTypeVector = std::vector<audio_stream_type_t>;
 
+/**
+ * Legacy audio policy product strategies IDs. These strategies are supported by the default
+ * policy engine.
+ */
+enum legacy_strategy {
+    STRATEGY_NONE = -1,
+    STRATEGY_MEDIA,
+    STRATEGY_PHONE,
+    STRATEGY_SONIFICATION,
+    STRATEGY_SONIFICATION_RESPECTFUL,
+    STRATEGY_DTMF,
+    STRATEGY_ENFORCED_AUDIBLE,
+    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
+    STRATEGY_ACCESSIBILITY,
+    STRATEGY_REROUTING,
+    STRATEGY_CALL_ASSISTANT,
+    STRATEGY_PATCH,
+};
+
 static const audio_attributes_t defaultAttr = AUDIO_ATTRIBUTES_INITIALIZER;
 
 static const std::set<audio_usage_t > gHighPriorityUseCases = {
diff --git a/services/audiopolicy/common/managerdefinitions/Android.bp b/services/audiopolicy/common/managerdefinitions/Android.bp
index e8b04ce..051e975 100644
--- a/services/audiopolicy/common/managerdefinitions/Android.bp
+++ b/services/audiopolicy/common/managerdefinitions/Android.bp
@@ -42,6 +42,7 @@
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
         "libaudiopolicy",
+        "libaudioutils",
         "libbase",
         "libcutils",
         "libhidlbase",
@@ -56,9 +57,6 @@
         "libmedia",
         "libmedia_helper",
     ],
-    static_libs: [
-        "libaudioutils",
-    ],
     header_libs: [
         "libaudiopolicycommon",
         "libaudiopolicymanager_interface_headers",
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
index 6167f95..e519766 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
@@ -47,13 +47,17 @@
 
     if (active) {
         // On MMAP IOs, the preferred device is selected by the first client (virtual client
-        // created when the mmap stream is opened). This client is never active.
+        // created when the mmap stream is opened). This client is never active and we only
+        // consider the Filter criteria, not the active state.
         // On non MMAP IOs, the preferred device is honored only if all active clients have
         // a preferred device in which case the first client drives the selection.
         if (desc->isMmap()) {
-            // The client list is never empty on a MMAP IO
-            return devices.getDeviceFromId(
-                    desc->clientsList(false /*activeOnly*/)[0]->preferredDeviceId());
+            auto matchingClients = desc->clientsList(
+                    false /*activeOnly*/, filter, false /*preferredDevice*/);
+            if (matchingClients.empty()) {
+                return nullptr;
+            }
+            return devices.getDeviceFromId(matchingClients[0]->preferredDeviceId());
         } else {
             auto activeClientsWithRoute =
                 desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 914f3fe..bfb28a5 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -413,7 +413,8 @@
                       const DeviceVector &devices,
                       audio_stream_type_t stream,
                       audio_output_flags_t flags,
-                      audio_io_handle_t *output);
+                      audio_io_handle_t *output,
+                      audio_attributes_t attributes);
 
         // Called when a stream is about to be started
         // Note: called before setClientActive(true);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index 80fa863..b193cb8 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -49,6 +49,7 @@
     static const constexpr char* const kDefaultConfigSource = "AudioPolicyConfig::setDefault";
     // The suffix of the "engine default" implementation shared library name.
     static const constexpr char* const kDefaultEngineLibraryNameSuffix = "default";
+    static const constexpr char* const kCapEngineLibraryNameSuffix = "configurable";
 
     // Creates the default (fallback) configuration.
     static sp<const AudioPolicyConfig> createDefault();
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index a596c43..60da405 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -63,6 +63,8 @@
      * HW Audio Source.
      */
     virtual bool isInternal() const { return false; }
+    virtual bool isCallRx() const { return false; }
+    virtual bool isCallTx() const { return false; }
     audio_port_handle_t portId() const { return mPortId; }
     uid_t uid() const { return mUid; }
     audio_session_t session() const { return mSessionId; };
@@ -236,7 +238,7 @@
                            const sp<DeviceDescriptor>& srcDevice,
                            audio_stream_type_t stream, product_strategy_t strategy,
                            VolumeSource volumeSource,
-                           bool isInternal);
+                           bool isInternal, bool isCallRx, bool isCallTx);
 
     ~SourceClientDescriptor() override = default;
 
@@ -263,6 +265,8 @@
     wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
     void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput);
     bool isInternal() const override { return mIsInternal; }
+    bool isCallRx() const override { return mIsCallRx; }
+    bool isCallTx() const override { return mIsCallTx; }
 
     using ClientDescriptor::dump;
     void dump(String8 *dst, int spaces) const override;
@@ -294,6 +298,8 @@
      * requester to prevent rerouting SwOutput involved in raw patches.
      */
     bool mIsInternal = false;
+    bool mIsCallRx = false;
+    bool mIsCallTx = false;
 };
 
 class SourceClientCollection :
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index b92cd70..f7b9b33 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -99,21 +99,20 @@
      * @return ioHandle if found, AUDIO_IO_HANDLE_NONE otherwise.
      */
     audio_io_handle_t getIoForSession(audio_session_t sessionId,
-                                      const effect_uuid_t *effectType = nullptr) const;
-    bool hasOrphansForSession(audio_session_t sessionId) const;
-    EffectDescriptorCollection getOrphanEffectsForSession(audio_session_t sessionId) const;
-    void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
+                                      const effect_uuid_t* effectType = nullptr) const;
 
     /**
-     * @brief Checks if there is at least one orphan effect with given sessionId and effect type
-     * uuid.
+     * @brief Checks if there is at least one orphan effect with given sessionId and optional effect
+     * type uuid.
      * @param sessionId Session ID.
-     * @param effectType Effect type UUID, the implementation will be same as hasOrphansForSession
-     * if null.
+     * @param effectType Optional effect type UUID pointer to effect_uuid_t, nullptr by default.
      * @return True if there is an orphan effect for given sessionId and type UUID, false otherwise.
      */
-    bool hasOrphanEffectsForSessionAndType(audio_session_t sessionId,
-                                           const effect_uuid_t* effectType) const;
+    bool hasOrphansForSession(audio_session_t sessionId,
+                              const effect_uuid_t* effectType = nullptr) const;
+
+    EffectDescriptorCollection getOrphanEffectsForSession(audio_session_t sessionId) const;
+    void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
 
 private:
     status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 68b2e7b..a8663fa 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -588,7 +588,8 @@
                                        const DeviceVector &devices,
                                        audio_stream_type_t stream,
                                        audio_output_flags_t flags,
-                                       audio_io_handle_t *output)
+                                       audio_io_handle_t *output,
+                                       audio_attributes_t attributes)
 {
     mDevices = devices;
     sp<DeviceDescriptor> device = devices.getDeviceForOpening();
@@ -652,7 +653,8 @@
                                                    &lMixerConfig,
                                                    device,
                                                    &mLatency,
-                                                   mFlags);
+                                                   mFlags,
+                                                   attributes);
 
     if (status == NO_ERROR) {
         LOG_ALWAYS_FATAL_IF(*output == AUDIO_IO_HANDLE_NONE,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
index 58d7fc7..f5e135e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyConfig.cpp
@@ -270,6 +270,9 @@
     mSurroundFormats = VALUE_OR_RETURN_STATUS(
             aidl2legacy_SurroundSoundConfig_SurroundFormats(aidl.surroundSoundConfig));
     mSource = kAidlConfigSource;
+    if (aidl.engineConfig.capSpecificConfig.has_value()) {
+        setEngineLibraryNameSuffix(kCapEngineLibraryNameSuffix);
+    }
     // No need to augmentData() as AIDL HAL must provide correct mic addresses.
     return NO_ERROR;
 }
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 667c189..ad6977b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -96,12 +96,14 @@
 SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
          audio_attributes_t attributes, const struct audio_port_config &config,
          const sp<DeviceDescriptor>& srcDevice, audio_stream_type_t stream,
-         product_strategy_t strategy, VolumeSource volumeSource, bool isInternal) :
+         product_strategy_t strategy, VolumeSource volumeSource,
+         bool isInternal, bool isCallRx, bool isCallTx) :
     TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
         {config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE,
         stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false,
         {} /* Sources do not support secondary outputs*/, nullptr),
-    mSrcDevice(srcDevice), mIsInternal(isInternal)
+    mSrcDevice(srcDevice), mIsInternal(isInternal),
+    mIsCallRx(isCallRx), mIsCallTx(isCallTx)
 {
 }
 
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 7971b61..090da6c 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -210,27 +210,13 @@
     }
 }
 
-bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId) const
-{
+bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId,
+                                                      const effect_uuid_t* effectType) const {
     for (size_t i = 0; i < size(); ++i) {
         sp<EffectDescriptor> effect = valueAt(i);
-        if (effect->mSession == sessionId && effect->mIsOrphan) {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool EffectDescriptorCollection::hasOrphanEffectsForSessionAndType(
-        audio_session_t sessionId, const effect_uuid_t* effectType) const {
-    if (effectType == nullptr) {
-        return hasOrphansForSession(sessionId);
-    }
-
-    for (size_t i = 0; i < size(); ++i) {
-        sp<EffectDescriptor> effect = valueAt(i);
-        if (effect->mIsOrphan && effect->mSession == sessionId &&
-            memcmp(&effect->mDesc.type, effectType, sizeof(effect_uuid_t)) == 0) {
+        if (effect->mSession == sessionId && effect->mIsOrphan &&
+            (effectType == nullptr ||
+             memcmp(&effect->mDesc.type, effectType, sizeof(effect_uuid_t)) == 0)) {
             return true;
         }
     }
diff --git a/services/audiopolicy/engine/common/Android.bp b/services/audiopolicy/engine/common/Android.bp
index d8aac37..7daa064 100644
--- a/services/audiopolicy/engine/common/Android.bp
+++ b/services/audiopolicy/engine/common/Android.bp
@@ -64,5 +64,6 @@
     ],
     defaults: [
         "aconfig_lib_cc_static_link.defaults",
+        "latest_android_media_audio_common_types_cpp_static",
     ],
 }
diff --git a/services/audiopolicy/engine/common/include/EngineBase.h b/services/audiopolicy/engine/common/include/EngineBase.h
index b9c94a4..edb2e29 100644
--- a/services/audiopolicy/engine/common/include/EngineBase.h
+++ b/services/audiopolicy/engine/common/include/EngineBase.h
@@ -129,6 +129,8 @@
 
     product_strategy_t getProductStrategyByName(const std::string &name) const;
 
+    std::string getProductStrategyName(product_strategy_t id) const;
+
     AudioPolicyManagerObserver *getApmObserver() const { return mApmObserver; }
 
     inline bool isInCall() const
diff --git a/services/audiopolicy/engine/common/include/ProductStrategy.h b/services/audiopolicy/engine/common/include/ProductStrategy.h
index 1593be0..8162720 100644
--- a/services/audiopolicy/engine/common/include/ProductStrategy.h
+++ b/services/audiopolicy/engine/common/include/ProductStrategy.h
@@ -46,7 +46,7 @@
     using VolumeGroupAttributesVector = std::vector<VolumeGroupAttributes>;
 
 public:
-    ProductStrategy(const std::string &name);
+    ProductStrategy(const std::string &name, int id = PRODUCT_STRATEGY_NONE);
 
     void addAttributes(const VolumeGroupAttributes &volumeGroupAttributes);
 
diff --git a/services/audiopolicy/engine/common/src/EngineBase.cpp b/services/audiopolicy/engine/common/src/EngineBase.cpp
index e259e6e..976791f 100644
--- a/services/audiopolicy/engine/common/src/EngineBase.cpp
+++ b/services/audiopolicy/engine/common/src/EngineBase.cpp
@@ -116,6 +116,15 @@
     return PRODUCT_STRATEGY_NONE;
 }
 
+std::string EngineBase::getProductStrategyName(product_strategy_t id) const {
+    for (const auto &iter : mProductStrategies) {
+        if (iter.second->getId() == id) {
+            return iter.second->getName();
+        }
+    }
+    return "";
+}
+
 engineConfig::ParsingResult EngineBase::loadAudioPolicyEngineConfig(
         const media::audio::common::AudioHalEngineConfig& aidlConfig)
 {
@@ -240,7 +249,7 @@
         loadVolumeConfig(mVolumeGroups, volumeConfig);
     }
     for (auto& strategyConfig : result.parsedConfig->productStrategies) {
-        sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name);
+        sp<ProductStrategy> strategy = new ProductStrategy(strategyConfig.name, strategyConfig.id);
         for (const auto &group : strategyConfig.attributesGroups) {
             const auto &iter = std::find_if(begin(mVolumeGroups), end(mVolumeGroups),
                                          [&group](const auto &volumeGroup) {
diff --git a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
index 548a20d..c4bf64a 100644
--- a/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
+++ b/services/audiopolicy/engine/common/src/EngineDefaultConfig.h
@@ -18,14 +18,17 @@
 
 #include <EngineConfig.h>
 
+#include <media/AudioProductStrategy.h>
+#include <policy.h>
 #include <system/audio.h>
 
 namespace android {
+
 /**
  * @brief AudioProductStrategies hard coded array of strategies to fill new engine API contract.
  */
 const engineConfig::ProductStrategies gOrderedStrategies = {
-    {"STRATEGY_PHONE",
+    {"STRATEGY_PHONE", STRATEGY_PHONE,
      {
          {AUDIO_STREAM_VOICE_CALL, "AUDIO_STREAM_VOICE_CALL",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VOICE_COMMUNICATION, AUDIO_SOURCE_DEFAULT,
@@ -37,7 +40,7 @@
          }
      },
     },
-    {"STRATEGY_SONIFICATION",
+    {"STRATEGY_SONIFICATION", STRATEGY_SONIFICATION,
      {
          {AUDIO_STREAM_RING, "AUDIO_STREAM_RING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE,
@@ -49,7 +52,7 @@
          }
      },
     },
-    {"STRATEGY_ENFORCED_AUDIBLE",
+    {"STRATEGY_ENFORCED_AUDIBLE", STRATEGY_ENFORCED_AUDIBLE,
      {
          {AUDIO_STREAM_ENFORCED_AUDIBLE, "AUDIO_STREAM_ENFORCED_AUDIBLE",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
@@ -57,7 +60,7 @@
          }
      },
     },
-    {"STRATEGY_ACCESSIBILITY",
+    {"STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY,
      {
          {AUDIO_STREAM_ACCESSIBILITY, "AUDIO_STREAM_ACCESSIBILITY",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY,
@@ -65,7 +68,7 @@
          }
      },
     },
-    {"STRATEGY_SONIFICATION_RESPECTFUL",
+    {"STRATEGY_SONIFICATION_RESPECTFUL", STRATEGY_SONIFICATION_RESPECTFUL,
      {
          {AUDIO_STREAM_NOTIFICATION, "AUDIO_STREAM_NOTIFICATION",
           {
@@ -77,7 +80,7 @@
          }
      },
     },
-    {"STRATEGY_MEDIA",
+    {"STRATEGY_MEDIA", STRATEGY_MEDIA,
      {
          {AUDIO_STREAM_ASSISTANT, "AUDIO_STREAM_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_SPEECH, AUDIO_USAGE_ASSISTANT,
@@ -103,7 +106,7 @@
          }
      },
     },
-    {"STRATEGY_DTMF",
+    {"STRATEGY_DTMF", STRATEGY_DTMF,
      {
          {AUDIO_STREAM_DTMF, "AUDIO_STREAM_DTMF",
           {
@@ -113,7 +116,7 @@
          }
      },
     },
-    {"STRATEGY_CALL_ASSISTANT",
+    {"STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT,
      {
          {AUDIO_STREAM_CALL_ASSISTANT, "AUDIO_STREAM_CALL_ASSISTANT",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_CALL_ASSISTANT, AUDIO_SOURCE_DEFAULT,
@@ -121,7 +124,7 @@
          }
      },
     },
-    {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER",
+    {"STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
      {
          {AUDIO_STREAM_TTS, "AUDIO_STREAM_TTS",
           {
@@ -140,7 +143,7 @@
  * For compatibility reason why apm volume config file, volume group name is the stream type.
  */
 const engineConfig::ProductStrategies gOrderedSystemStrategies = {
-    {"STRATEGY_REROUTING",
+    {"STRATEGY_REROUTING", STRATEGY_REROUTING,
      {
          {AUDIO_STREAM_REROUTING, "AUDIO_STREAM_REROUTING",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_VIRTUAL_SOURCE, AUDIO_SOURCE_DEFAULT,
@@ -148,7 +151,7 @@
          }
      },
     },
-    {"STRATEGY_PATCH",
+    {"STRATEGY_PATCH", STRATEGY_PATCH,
      {
          {AUDIO_STREAM_PATCH, "AUDIO_STREAM_PATCH",
           {{AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT,
diff --git a/services/audiopolicy/engine/common/src/ProductStrategy.cpp b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
index 0d25955..8ed7403 100644
--- a/services/audiopolicy/engine/common/src/ProductStrategy.cpp
+++ b/services/audiopolicy/engine/common/src/ProductStrategy.cpp
@@ -19,6 +19,7 @@
 
 #include "ProductStrategy.h"
 
+#include <android/media/audio/common/AudioHalProductStrategy.h>
 #include <media/AudioProductStrategy.h>
 #include <media/TypeConverter.h>
 #include <utils/String8.h>
@@ -30,11 +31,20 @@
 
 namespace android {
 
-ProductStrategy::ProductStrategy(const std::string &name) :
+using media::audio::common::AudioHalProductStrategy;
+
+/*
+ * Note on the id: either is provided (legacy strategies have hard coded id, aidl have
+ * own id, enforced to be started from VENDOR_STRATEGY_ID_START.
+ * REROUTING & PATCH system strategies are added.
+ * To prevent from collision, generate from VENDOR_STRATEGY_ID_START when id is not provided.
+ */
+ProductStrategy::ProductStrategy(const std::string &name, int id) :
     mName(name),
-    mId(static_cast<product_strategy_t>(HandleGenerator<uint32_t>::getNextHandle()))
-{
-}
+    mId((static_cast<product_strategy_t>(id) != PRODUCT_STRATEGY_NONE) ?
+            static_cast<product_strategy_t>(id) :
+            static_cast<product_strategy_t>(AudioHalProductStrategy::VENDOR_STRATEGY_ID_START +
+                    HandleGenerator<uint32_t>::getNextHandle())) {}
 
 void ProductStrategy::addAttributes(const VolumeGroupAttributes &volumeGroupAttributes)
 {
diff --git a/services/audiopolicy/engine/config/Android.bp b/services/audiopolicy/engine/config/Android.bp
index ab2c134..d771605 100644
--- a/services/audiopolicy/engine/config/Android.bp
+++ b/services/audiopolicy/engine/config/Android.bp
@@ -10,6 +10,9 @@
 
 cc_library {
     name: "libaudiopolicyengine_config",
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
     export_include_dirs: ["include"],
     include_dirs: [
         "external/libxml2/include",
diff --git a/services/audiopolicy/engine/config/include/EngineConfig.h b/services/audiopolicy/engine/config/include/EngineConfig.h
index 119dbd6..054bdae 100644
--- a/services/audiopolicy/engine/config/include/EngineConfig.h
+++ b/services/audiopolicy/engine/config/include/EngineConfig.h
@@ -71,6 +71,7 @@
 
 struct ProductStrategy {
     std::string name;
+    int id;
     AttributesGroups attributesGroups;
 };
 
diff --git a/services/audiopolicy/engine/config/src/EngineConfig.cpp b/services/audiopolicy/engine/config/src/EngineConfig.cpp
index 3f9ae19..714ab78 100644
--- a/services/audiopolicy/engine/config/src/EngineConfig.cpp
+++ b/services/audiopolicy/engine/config/src/EngineConfig.cpp
@@ -20,7 +20,6 @@
 #include <sstream>
 #include <stdarg.h>
 #include <string>
-#include <string>
 #include <vector>
 #include <unordered_map>
 
@@ -42,6 +41,7 @@
 
 namespace android {
 
+using media::audio::common::AudioStreamType;
 using utilities::convertTo;
 
 namespace engineConfig {
@@ -66,6 +66,9 @@
                             STRATEGY_ENTRY(ACCESSIBILITY)};
 #undef STRATEGY_ENTRY
 
+    if (id >= media::audio::common::AudioHalProductStrategy::VENDOR_STRATEGY_ID_START) {
+        return std::to_string(id);
+    }
     auto it = productStrategyMap.find(id);
     if (it == productStrategyMap.end()) {
         return base::unexpected(BAD_VALUE);
@@ -76,8 +79,12 @@
 ConversionResult<AttributesGroup> aidl2legacy_AudioHalAttributeGroup_AttributesGroup(
         const media::audio::common::AudioHalAttributesGroup& aidl) {
     AttributesGroup legacy;
-    legacy.stream = VALUE_OR_RETURN(
-            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+    // StreamType may only be set to AudioStreamType.INVALID when using the
+    // Configurable Audio Policy (CAP) engine. An AudioHalAttributesGroup with
+    // AudioStreamType.INVALID is used when the volume group and attributes are
+    // not associated to any AudioStreamType.
+    legacy.stream = ((aidl.streamType == AudioStreamType::INVALID) ? AUDIO_STREAM_DEFAULT :
+            VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType)));
     legacy.volumeGroup = aidl.volumeGroupName;
     legacy.attributesVect = VALUE_OR_RETURN(convertContainer<AttributesVector>(
                     aidl.attributes, aidl2legacy_AudioAttributes_audio_attributes_t));
@@ -87,8 +94,9 @@
 ConversionResult<ProductStrategy> aidl2legacy_AudioHalProductStrategy_ProductStrategy(
         const media::audio::common::AudioHalProductStrategy& aidl) {
     ProductStrategy legacy;
-    legacy.name = VALUE_OR_RETURN(
-                    aidl2legacy_AudioHalProductStrategy_ProductStrategyType(aidl.id));
+    legacy.name = aidl.name.value_or(VALUE_OR_RETURN(
+                    aidl2legacy_AudioHalProductStrategy_ProductStrategyType(aidl.id)));
+    legacy.id = aidl.id;
     legacy.attributesGroups = VALUE_OR_RETURN(convertContainer<AttributesGroups>(
                     aidl.attributesGroups,
                     aidl2legacy_AudioHalAttributeGroup_AttributesGroup));
@@ -148,7 +156,6 @@
                     aidl.volumeCurves, aidl2legacy_AudioHalVolumeCurve_VolumeCurve));
     return legacy;
 }
-
 }  // namespace
 
 template<typename E, typename C>
@@ -175,6 +182,7 @@
 
     struct Attributes {
         static constexpr const char *name = "name";
+        static constexpr const char *id = "id";
     };
     static android::status_t deserialize(_xmlDoc *doc, const _xmlNode *root, Collection &ps);
 };
@@ -533,13 +541,21 @@
         ALOGE("ProductStrategyTraits No attribute %s found", Attributes::name);
         return BAD_VALUE;
     }
+    int id = PRODUCT_STRATEGY_NONE;
+    std::string idLiteral = getXmlAttribute(child, Attributes::id);
+    if (!idLiteral.empty()) {
+        if (!convertTo(idLiteral, id)) {
+            return BAD_VALUE;
+        }
+        ALOGV("%s: %s, %s = %d", __FUNCTION__, name.c_str(), Attributes::id, id);
+    }
     ALOGV("%s: %s = %s", __FUNCTION__, Attributes::name, name.c_str());
 
     size_t skipped = 0;
     AttributesGroups attrGroups;
     deserializeCollection<AttributesGroupTraits>(doc, child, attrGroups, skipped);
 
-    strategies.push_back({name, attrGroups});
+    strategies.push_back({name, id, attrGroups});
     return NO_ERROR;
 }
 
diff --git a/services/audiopolicy/engineconfigurable/Android.bp b/services/audiopolicy/engineconfigurable/Android.bp
index a0a4bdf..1c98faf 100644
--- a/services/audiopolicy/engineconfigurable/Android.bp
+++ b/services/audiopolicy/engineconfigurable/Android.bp
@@ -36,10 +36,10 @@
         "libbase_headers",
     ],
     static_libs: [
+        "libaudiopolicycapengine_config",
         "libaudiopolicyengine_common",
         "libaudiopolicyengine_config",
         "libaudiopolicyengineconfigurable_pfwwrapper",
-
     ],
     shared_libs: [
         "libaudio_aidl_conversion_common_cpp",
@@ -56,5 +56,13 @@
     ],
     defaults: [
         "aconfig_lib_cc_static_link.defaults",
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+    required: [
+        "CapClass.xml",
+        "CapProductStrategies.xml",
+        "CapSubsystem-CommonTypes.xml",
+        "CapSubsystem.xml",
+        "ParameterFrameworkConfigurationCap.xml",
     ],
 }
diff --git a/services/audiopolicy/engineconfigurable/config/Android.bp b/services/audiopolicy/engineconfigurable/config/Android.bp
index 8dd13e8..95a7cf8 100644
--- a/services/audiopolicy/engineconfigurable/config/Android.bp
+++ b/services/audiopolicy/engineconfigurable/config/Android.bp
@@ -38,6 +38,53 @@
 }
 
 filegroup {
+    name: "audio_policy_engine_aidl_criterion_types_template",
+    srcs: ["example/common/audio_policy_engine_criterion_types_aidl.xml.in"],
+}
+
+filegroup {
     name: "audio_policy_engine_criteria",
     srcs: ["example/common/audio_policy_engine_criteria.xml"],
 }
+
+cc_library_headers {
+    name: "libaudiopolicycapengine_config_headers",
+    export_include_dirs: ["include"],
+}
+
+cc_library {
+    name: "libaudiopolicycapengine_config",
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+    export_header_lib_headers: [
+        "libaudiopolicycapengine_config_headers",
+    ],
+    include_dirs: [
+        "external/libxml2/include",
+    ],
+    srcs: [
+        "src/CapEngineConfig.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudiopolicycomponents",
+        "libaudiopolicyengine_config",
+        "libcutils",
+        "liblog",
+        "libmedia_helper",
+        "libutils",
+        "libxml2",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+        "libaudioclient_headers",
+        "libaudiopolicycapengine_config_headers",
+        "libmedia_headers",
+    ],
+}
diff --git a/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in
new file mode 100644
index 0000000..dc2517b
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/example/common/audio_policy_engine_criterion_types_aidl.xml.in
@@ -0,0 +1,96 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<criterion_types>
+    <criterion_type name="OutputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="InputDevicesMaskType" type="inclusive"/>
+    <criterion_type name="OutputDevicesAddressesType" type="inclusive">
+        <values>
+            <!-- legacy remote submix -->
+            <value literal="0" numerical="1"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="InputDevicesAddressesType" type="inclusive">
+        <values>
+            <!-- legacy remote submix -->
+            <value literal="0" numerical="1"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="AndroidModeType" type="exclusive"/>
+    <criterion_type name="ForceUseForCommunicationType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="SPEAKER" numerical="1"/>
+            <value literal="BT_SCO" numerical="3"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForMediaType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="SPEAKER" numerical="1"/>
+            <value literal="HEADPHONES" numerical="2"/>
+            <value literal="BT_A2DP" numerical="4"/>
+            <value literal="WIRED_ACCESSORY" numerical="5"/>
+            <value literal="ANALOG_DOCK" numerical="8"/>
+            <value literal="DIGITAL_DOCK" numerical="9"/>
+            <value literal="NO_BT_A2DP" numerical="10"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForRecordType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="BT_SCO" numerical="3"/>
+            <value literal="WIRED_ACCESSORY" numerical="5"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForDockType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="WIRED_ACCESSORY" numerical="5"/>
+            <value literal="BT_CAR_DOCK" numerical="6"/>
+            <value literal="BT_DESK_DOCK" numerical="7"/>
+            <value literal="ANALOG_DOCK" numerical="8"/>
+            <value literal="DIGITAL_DOCK" numerical="9"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForSystemType" type="exclusive" >
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="SYSTEM_ENFORCED" numerical="11"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForHdmiSystemAudioType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="HDMI_SYSTEM_AUDIO_ENFORCED" numerical="12"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForEncodedSurroundType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="ENCODED_SURROUND_NEVER" numerical="13"/>
+            <value literal="ENCODED_SURROUND_ALWAYS" numerical="14"/>
+            <value literal="ENCODED_SURROUND_MANUAL" numerical="15"/>
+        </values>
+    </criterion_type>
+    <criterion_type name="ForceUseForVibrateRingingType" type="exclusive">
+        <values>
+            <value literal="NONE" numerical="0"/>
+            <value literal="BT_SCO" numerical="3"/>
+        </values>
+    </criterion_type>
+</criterion_types>
+
+
diff --git a/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h b/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h
new file mode 100644
index 0000000..6c55a49
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/include/CapEngineConfig.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <EngineConfig.h>
+
+#include <android/media/audio/common/AudioHalEngineConfig.h>
+#include <system/audio_policy.h>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace capEngineConfig {
+
+static const char *const gCriterionTypeSuffix = "Type";
+static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
+static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
+static const char *const gPhoneStateCriterionName = "TelephonyMode";
+static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
+static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
+
+/**
+* Order MUST be aligned with definition of audio_policy_force_use_t within audio_policy.h
+*/
+static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
+{
+    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
+    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
+    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
+    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
+    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
+    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
+    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
+    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
+};
+
+using ParameterValues = std::vector<std::string>;
+
+struct ConfigurableElement {
+    std::string path;
+};
+
+struct ConfigurableElementValue {
+    ConfigurableElement configurableElement;
+    std::string value;
+};
+using ConfigurableElementValues = std::vector<ConfigurableElementValue>;
+
+struct CapSetting {
+    std::string configurationName;
+    ConfigurableElementValues configurableElementValues;
+};
+using CapSettings = std::vector<CapSetting>;
+
+struct CapConfiguration {
+    std::string name;
+    std::string rule;
+};
+
+using ConfigurableElementPaths = std::vector<std::string>;
+using CapConfigurations = std::vector<CapConfiguration>;
+
+struct CapConfigurableDomain {
+    std::string name;
+    CapConfigurations configurations;
+    CapSettings settings;
+};
+
+struct CapCriterion {
+    engineConfig::Criterion criterion;
+    engineConfig::CriterionType criterionType;
+};
+
+using CapCriteria = std::vector<CapCriterion>;
+using CapConfigurableDomains = std::vector<CapConfigurableDomain>;
+
+struct CapConfig {
+    CapCriteria capCriteria;
+    CapConfigurableDomains capConfigurableDomains;
+};
+
+/** Result of `parse(const char*)` */
+struct ParsingResult {
+    /** Parsed config, nullptr if the xml lib could not load the file */
+    std::unique_ptr<CapConfig> parsedConfig;
+    size_t nbSkippedElement; //< Number of skipped invalid product strategies
+};
+
+/** Convert the provided Cap Settings configuration.
+ * @return audio policy usage @see Config
+ */
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig);
+
+}
+}
diff --git a/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp b/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp
new file mode 100644
index 0000000..a1b4470
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/config/src/CapEngineConfig.cpp
@@ -0,0 +1,500 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cinttypes>
+#include <cstdint>
+#include <istream>
+#include <map>
+#include <sstream>
+#include <stdarg.h>
+#include <string>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "APM::AudioPolicyEngine/CapConfig"
+//#define LOG_NDEBUG 0
+
+#include "CapEngineConfig.h"
+#include <TypeConverter.h>
+#include <Volume.h>
+#include <cutils/properties.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <media/TypeConverter.h>
+#include <media/convert.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+namespace android {
+
+using utilities::convertTo;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioHalCapCriterion;
+using media::audio::common::AudioHalCapParameter;
+using media::audio::common::AudioHalCapRule;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioHalCapCriterionV2;
+using ::android::base::unexpected;
+
+namespace capEngineConfig {
+
+static constexpr const char *gLegacyOutputDevicePrefix = "AUDIO_DEVICE_OUT_";
+static constexpr const char *gLegacyInputDevicePrefix = "AUDIO_DEVICE_IN_";
+static constexpr const char *gLegacyStreamPrefix = "AUDIO_STREAM_";
+static constexpr const char *gLegacySourcePrefix = "AUDIO_SOURCE_";
+static constexpr const char *gPolicyParamPrefix = "/Policy/policy/";
+
+namespace {
+
+ConversionResult<std::string> truncatePrefixToLower(const std::string& legacyName,
+                                                    const std::string& legacyPrefix) {
+    std::size_t pos = legacyName.find(legacyPrefix);
+    if (pos == std::string::npos) {
+        return unexpected(BAD_VALUE);
+    }
+    std::string capName = legacyName.substr(pos + legacyPrefix.length());
+    std::transform(capName.begin(), capName.end(), capName.begin(),
+                   [](unsigned char c) { return std::tolower(c); });
+    return capName;
+}
+
+ConversionResult<std::string> truncatePrefix(const std::string& name,  const std::string& prefix) {
+    std::size_t pos = name.find(prefix);
+    if (pos == std::string::npos) {
+        return unexpected(BAD_VALUE);
+    }
+    std::string capName = name.substr(pos + prefix.length());
+    return capName;
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2_CapName(
+        const AudioHalCapCriterionV2& aidl) {
+    switch (aidl.getTag()) {
+        case AudioHalCapCriterionV2::availableInputDevices:
+            return gInputDeviceCriterionName;
+        case AudioHalCapCriterionV2::availableOutputDevices:
+            return gOutputDeviceCriterionName;
+        case AudioHalCapCriterionV2::availableInputDevicesAddresses:
+            return gInputDeviceAddressCriterionName;
+        case AudioHalCapCriterionV2::availableOutputDevicesAddresses:
+            return gOutputDeviceAddressCriterionName;
+        case AudioHalCapCriterionV2::telephonyMode:
+            return gPhoneStateCriterionName;
+        case AudioHalCapCriterionV2::forceConfigForUse: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
+            return gForceUseCriterionTag[VALUE_OR_RETURN(
+                    aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+                            aidlCriterion.forceUse))];
+        }
+        default:
+            return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
+        const AudioDeviceDescription& aidl) {
+    audio_devices_t legacyDeviceType = VALUE_OR_RETURN(
+            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl));
+    bool isOut = audio_is_output_devices(legacyDeviceType);
+    std::string legacyTypeLiteral;
+    if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
+        ALOGE("%s Invalid strategy device type %d", __func__, legacyDeviceType);
+        return unexpected(BAD_VALUE);
+    }
+    return truncatePrefix(legacyTypeLiteral,
+            isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix);
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
+        const AudioHalCapCriterionV2::Type& aidl) {
+    switch (aidl.getTag()) {
+        case AudioHalCapCriterionV2::Type::availableDevicesType:
+            return aidl2legacy_AudioHalCapCriterionV2TypeDevice_CapCriterionValue(
+                    aidl.get<AudioHalCapCriterionV2::Type::availableDevicesType>());
+        case AudioHalCapCriterionV2::Type::availableDevicesAddressesType:
+            return aidl.get<AudioHalCapCriterionV2::Type::availableDevicesAddressesType>().template
+                    get<AudioDeviceAddress::id>();
+        case AudioHalCapCriterionV2::Type::telephonyModeType:
+            return toString(aidl.get<AudioHalCapCriterionV2::Type::telephonyModeType>());
+        case AudioHalCapCriterionV2::Type::forcedConfigType:
+            return toString(aidl.get<AudioHalCapCriterionV2::Type::forcedConfigType>());
+        default:
+            return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<std::string> aidl2legacy_AudioHalCapRule_CapRule(
+        const AudioHalCapRule& aidlRule) {
+    std::string rule;
+    switch (aidlRule.compoundRule) {
+        case AudioHalCapRule::CompoundRule::ANY:
+            rule += "Any";
+            break;
+        case AudioHalCapRule::CompoundRule::ALL:
+            rule += "All";
+            break;
+        default:
+            return unexpected(BAD_VALUE);
+    }
+    rule += "{";
+    if (!aidlRule.nestedRules.empty()) {
+        for (const auto& nestedRule: aidlRule.nestedRules) {
+            rule += VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(nestedRule));
+        }
+        if (!aidlRule.criterionRules.empty()) {
+            rule += ",";
+        }
+    }
+    bool isFirstCriterionRule = true;
+    for (const auto& criterionRule: aidlRule.criterionRules) {
+        if (!isFirstCriterionRule) {
+            rule += ",";
+        }
+        isFirstCriterionRule = false;
+        std::string selectionCriterion = VALUE_OR_RETURN(
+                aidl2legacy_AudioHalCapCriterionV2_CapName(criterionRule.criterion));
+        std::string matchesWhen;
+        std::string value = VALUE_OR_RETURN(
+                aidl2legacy_AudioHalCapCriterionV2Type_CapCriterionValue(
+                        criterionRule.criterionTypeValue));
+
+        switch (criterionRule.matchingRule) {
+            case AudioHalCapRule::MatchingRule::IS:
+                matchesWhen = "Is";
+                break;
+            case AudioHalCapRule::MatchingRule::IS_NOT:
+                matchesWhen = "IsNot";
+                break;
+            case AudioHalCapRule::MatchingRule::INCLUDES:
+                matchesWhen = "Includes";
+                break;
+            case AudioHalCapRule::MatchingRule::EXCLUDES:
+                matchesWhen = "Excludes";
+                break;
+            default:
+                return unexpected(BAD_VALUE);
+        }
+        rule += selectionCriterion + " " + matchesWhen + " " + value;
+    }
+    rule += "}";
+    return rule;
+}
+
+ConversionResult<CapConfiguration> aidl2legacy_AudioHalCapConfiguration_CapConfiguration(
+        const media::audio::common::AudioHalCapConfiguration& aidl) {
+    CapConfiguration legacy;
+    legacy.name = aidl.name;
+    legacy.rule = VALUE_OR_FATAL(aidl2legacy_AudioHalCapRule_CapRule(aidl.rule));
+    return legacy;
+}
+
+ConversionResult<ConfigurableElementValue> aidl2legacy_ParameterSetting_ConfigurableElementValue(
+        const AudioHalCapParameter& aidl) {
+    ConfigurableElementValue legacy;
+    std::string literalValue;
+    switch (aidl.getTag()) {
+        case AudioHalCapParameter::selectedStrategyDevice: {
+            auto strategyDevice = aidl.get<AudioHalCapParameter::selectedStrategyDevice>();
+            literalValue = std::to_string(strategyDevice.isSelected);
+            audio_devices_t legacyType = VALUE_OR_RETURN(
+                    aidl2legacy_AudioDeviceDescription_audio_devices_t(strategyDevice.device));
+            std::string legacyTypeLiteral;
+            if (!::android::OutputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
+                ALOGE("%s Invalid device type %d", __func__, legacyType);
+                return unexpected(BAD_VALUE);
+            }
+            std::string deviceLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyTypeLiteral, gLegacyOutputDevicePrefix));
+            if (deviceLiteral == "default") {
+                deviceLiteral = "stub";
+            }
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix)
+                    + "product_strategies/vx_" + std::to_string(strategyDevice.id)
+                    + "/selected_output_devices/mask/" + deviceLiteral;
+            break;
+        }
+        case AudioHalCapParameter::strategyDeviceAddress: {
+            auto strategyAddress = aidl.get<AudioHalCapParameter::strategyDeviceAddress>();
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix)
+                    + "product_strategies/vx_" + std::to_string(strategyAddress.id)
+                    + "/device_address";
+            literalValue = strategyAddress.deviceAddress.get<AudioDeviceAddress::id>();
+            break;
+        }
+        case AudioHalCapParameter::selectedInputSourceDevice: {
+            auto inputSourceDevice = aidl.get<AudioHalCapParameter::selectedInputSourceDevice>();
+            literalValue = std::to_string(inputSourceDevice.isSelected);
+            audio_devices_t legacyType = VALUE_OR_RETURN(
+                    aidl2legacy_AudioDeviceDescription_audio_devices_t(inputSourceDevice.device));
+            std::string legacyTypeLiteral;
+            if (!::android::InputDeviceConverter::toString(legacyType, legacyTypeLiteral)) {
+                ALOGE("%s Invalid input source device type %d", __func__, legacyType);
+                return unexpected(BAD_VALUE);
+            }
+            std::string deviceLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyTypeLiteral, gLegacyInputDevicePrefix));
+            if (deviceLiteral == "default") {
+                deviceLiteral = "stub";
+            }
+            audio_source_t legacySource = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
+                    inputSourceDevice.inputSource));
+            std::string inputSourceLiteral;
+            if (!::android::SourceTypeConverter::toString(legacySource, inputSourceLiteral)) {
+                ALOGE("%s Invalid input source  %d", __func__, legacySource);
+                return unexpected(BAD_VALUE);
+            }
+            inputSourceLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(inputSourceLiteral, gLegacySourcePrefix));
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "input_sources/"
+                    + inputSourceLiteral + "/applicable_input_device/mask/" + deviceLiteral;
+            break;
+        }
+        case AudioHalCapParameter::streamVolumeProfile: {
+            auto streamVolumeProfile = aidl.get<AudioHalCapParameter::streamVolumeProfile>();
+            audio_stream_type_t legacyStreamType = VALUE_OR_RETURN(
+                    aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.stream));
+            std::string legacyStreamLiteral;
+            if (!::android::StreamTypeConverter::toString(legacyStreamType, legacyStreamLiteral)) {
+                ALOGE("%s Invalid stream type  %d", __func__, legacyStreamType);
+                return unexpected(BAD_VALUE);
+            }
+            legacyStreamLiteral = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyStreamLiteral, gLegacyStreamPrefix));
+
+            audio_stream_type_t legacyProfile = VALUE_OR_RETURN(
+                    aidl2legacy_AudioStreamType_audio_stream_type_t(streamVolumeProfile.profile));
+            std::string legacyProfileLiteral;
+            if (!::android::StreamTypeConverter::toString(legacyProfile, legacyProfileLiteral)) {
+                ALOGE("%s Invalid profile %d", __func__, legacyProfile);
+                return unexpected(BAD_VALUE);
+            }
+            literalValue = VALUE_OR_RETURN(
+                    truncatePrefixToLower(legacyProfileLiteral, gLegacyStreamPrefix));
+            legacy.configurableElement.path = std::string(gPolicyParamPrefix) + "streams/"
+                    + legacyStreamLiteral + "/applicable_volume_profile/volume_profile";
+            break;
+        }
+        default:
+            return unexpected(BAD_VALUE);
+    }
+    legacy.value = literalValue;
+    return legacy;
+}
+
+ConversionResult<CapSetting> aidl2legacy_AudioHalCapConfiguration_CapSetting(
+        const media::audio::common::AudioHalCapConfiguration& aidl) {
+    CapSetting legacy;
+    legacy.configurationName = aidl.name;
+    legacy.configurableElementValues = VALUE_OR_RETURN(convertContainer<ConfigurableElementValues>(
+            aidl.parameterSettings, aidl2legacy_ParameterSetting_ConfigurableElementValue));
+    return legacy;
+}
+
+ConversionResult<CapConfigurableDomain> aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(
+        const media::audio::common::AudioHalCapDomain& aidl) {
+    CapConfigurableDomain legacy;
+    legacy.name = aidl.name;
+    legacy.configurations = VALUE_OR_RETURN(convertContainer<CapConfigurations>(
+            aidl.configurations,
+            aidl2legacy_AudioHalCapConfiguration_CapConfiguration));
+    legacy.settings = VALUE_OR_RETURN(convertContainer<CapSettings>(
+            aidl.configurations,
+            aidl2legacy_AudioHalCapConfiguration_CapSetting));
+    return legacy;
+}
+
+ConversionResult<CapCriterion> aidl2legacy_AudioHalCapCriterionV2_Criterion(
+            const AudioHalCapCriterionV2& aidl) {
+    CapCriterion capCriterion;
+    engineConfig::Criterion& criterion = capCriterion.criterion;
+    engineConfig::CriterionType& criterionType = capCriterion.criterionType;
+
+    auto loadForceUseCriterion = [](const auto &aidlCriterion, auto &criterion,
+            auto &criterionType) -> status_t {
+        uint32_t legacyForceUse = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(
+                        aidlCriterion.forceUse));
+        criterion.typeName = criterionType.name;
+        criterionType.name = criterion.typeName + gCriterionTypeSuffix;
+        criterionType.isInclusive =
+                (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+        criterion.name = gForceUseCriterionTag[legacyForceUse];
+        criterion.defaultLiteralValue = toString(aidlCriterion.defaultValue);
+        if (aidlCriterion.values.empty()) {
+            return BAD_VALUE;
+        }
+        for (auto &value : aidlCriterion.values) {
+            uint32_t legacyForcedConfig = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioPolicyForcedConfig_audio_policy_forced_cfg_t(value));
+            criterionType.valuePairs.push_back({legacyForcedConfig, 0, toString(value)});
+        }
+        return NO_ERROR;
+    };
+
+    auto loadDevicesCriterion = [](const auto &aidlCriterion, auto &criterion,
+            auto &criterionType) -> status_t {
+        criterionType.name = criterion.name + gCriterionTypeSuffix;
+        criterionType.isInclusive =
+                (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+        criterion.typeName = criterionType.name;
+        int shift = 0;
+        if (aidlCriterion.values.empty()) {
+            return BAD_VALUE;
+        }
+        for (const auto &value : aidlCriterion.values) {
+            audio_devices_t legacyDeviceType = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioDeviceDescription_audio_devices_t(value));
+            bool isOut = audio_is_output_devices(legacyDeviceType);
+            std::string legacyTypeLiteral;
+            if (!::android::DeviceConverter::toString(legacyDeviceType, legacyTypeLiteral)) {
+                ALOGE("%s Invalid device type %d", __func__, legacyDeviceType);
+                return BAD_VALUE;
+            }
+            std::string deviceLiteral = VALUE_OR_RETURN_STATUS(truncatePrefix(legacyTypeLiteral,
+                    isOut ? gLegacyOutputDevicePrefix : gLegacyInputDevicePrefix));
+            uint64_t pfwCriterionValue = 1 << shift++;
+            criterionType.valuePairs.push_back(
+                    {pfwCriterionValue, static_cast<int32_t>(legacyDeviceType), deviceLiteral});
+            ALOGV("%s: adding %" PRIu64 " %d %s %s", __func__, pfwCriterionValue, legacyDeviceType,
+                    toString(value.type).c_str(), deviceLiteral.c_str());
+        }
+        return NO_ERROR;
+    };
+
+    auto loadDeviceAddressesCriterion = [](const auto &aidlCriterion, auto &criterion,
+            auto &criterionType) -> status_t {
+        criterionType.name = criterion.name + gCriterionTypeSuffix;
+        criterionType.isInclusive =
+                (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+        criterion.typeName = criterionType.name;
+        int shift = 0;
+        for (auto &value : aidlCriterion.values) {
+            uint64_t pfwCriterionValue = 1 << shift++;
+            if (value.getTag() != AudioDeviceAddress::id) {
+                return BAD_VALUE;
+            }
+            std::string address = value.template get<AudioDeviceAddress::id>();
+            criterionType.valuePairs.push_back({pfwCriterionValue, 0, address});
+        }
+        return NO_ERROR;
+    };
+
+    switch (aidl.getTag()) {
+        case AudioHalCapCriterionV2::availableInputDevices: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableInputDevices>();
+            criterion.name = gInputDeviceCriterionName;
+            if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::availableOutputDevices: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::availableOutputDevices>();
+            criterion.name = gOutputDeviceCriterionName;
+            if (loadDevicesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::availableInputDevicesAddresses: {
+            auto aidlCriterion =
+                    aidl.get<AudioHalCapCriterionV2::availableInputDevicesAddresses>();
+            criterion.name = gInputDeviceAddressCriterionName;
+            if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::availableOutputDevicesAddresses: {
+            auto aidlCriterion =
+                    aidl.get<AudioHalCapCriterionV2::availableOutputDevicesAddresses>();
+            criterion.name = gOutputDeviceAddressCriterionName;
+            if (loadDeviceAddressesCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::telephonyMode: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::telephonyMode>();
+            criterion.name = gPhoneStateCriterionName;
+            criterionType.name = criterion.name  + gCriterionTypeSuffix;
+            criterionType.isInclusive =
+                    (aidlCriterion.logic == AudioHalCapCriterionV2::LogicalDisjunction::INCLUSIVE);
+            criterion.typeName = criterionType.name;
+            criterion.defaultLiteralValue = toString( aidlCriterion.defaultValue);
+            if (aidlCriterion.values.empty()) {
+                return unexpected(BAD_VALUE);
+            }
+            for (auto &value : aidlCriterion.values) {
+                uint32_t legacyMode =
+                        VALUE_OR_RETURN(aidl2legacy_AudioMode_audio_mode_t(value));
+                criterionType.valuePairs.push_back({legacyMode, 0, toString(value)});
+            }
+            break;
+        }
+        case AudioHalCapCriterionV2::forceConfigForUse: {
+            auto aidlCriterion = aidl.get<AudioHalCapCriterionV2::forceConfigForUse>();
+            if (loadForceUseCriterion(aidlCriterion, criterion, criterionType) != NO_ERROR) {
+                return unexpected(BAD_VALUE);
+            }
+            break;
+        }
+        default:
+            return unexpected(BAD_VALUE);
+    }
+    return capCriterion;
+}
+
+}  // namespace
+
+ParsingResult convert(const ::android::media::audio::common::AudioHalEngineConfig& aidlConfig) {
+    auto config = std::make_unique<capEngineConfig::CapConfig>();
+
+    if (!aidlConfig.capSpecificConfig.has_value() ||
+            !aidlConfig.capSpecificConfig.value().domains.has_value()) {
+        ALOGE("%s: no Cap Engine config", __func__);
+        return ParsingResult{};
+    }
+    for (auto& aidlCriteria: aidlConfig.capSpecificConfig.value().criteriaV2.value()) {
+        if (aidlCriteria.has_value()) {
+            if (auto conv = aidl2legacy_AudioHalCapCriterionV2_Criterion(aidlCriteria.value());
+                    conv.ok()) {
+                config->capCriteria.push_back(std::move(conv.value()));
+            } else {
+                return ParsingResult{};
+            }
+        }
+    }
+    size_t skippedElement = 0;
+    for (auto& aidlDomain: aidlConfig.capSpecificConfig.value().domains.value()) {
+        if (aidlDomain.has_value()) {
+            if (auto conv = aidl2legacy_AudioHalCapDomain_CapConfigurableDomain(aidlDomain.value());
+                    conv.ok()) {
+                config->capConfigurableDomains.push_back(std::move(conv.value()));
+            } else {
+                return ParsingResult{};
+            }
+        } else {
+            skippedElement += 1;
+        }
+    }
+    return {.parsedConfig=std::move(config), .nbSkippedElement=skippedElement};
+}
+} // namespace capEngineConfig
+} // namespace android
diff --git a/services/audiopolicy/engineconfigurable/data/Android.bp b/services/audiopolicy/engineconfigurable/data/Android.bp
new file mode 100644
index 0000000..303cabc
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/Android.bp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_av_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_license"],
+}
+
+prebuilt_etc {
+    name: "CapClass.xml",
+    src: ":CapClass",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "CapSubsystem.xml",
+    src: ":CapSubsystem",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "CapSubsystem-CommonTypes.xml",
+    src: ":buildaidlcommontypesstructure_gen",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "CapProductStrategies.xml",
+    src: ":cap_product_strategies_structure",
+    sub_dir: "parameter-framework/Structure/Policy",
+}
+
+prebuilt_etc {
+    name: "ParameterFrameworkConfigurationCap.xml",
+    src: ":ParameterFrameworkConfigurationCapSrc_gen",
+    sub_dir: "parameter-framework",
+}
+
+genrule {
+    name: "ParameterFrameworkConfigurationCapSrc_gen",
+    out: ["ParameterFrameworkConfigurationCap.xml"],
+    srcs: [":ParameterFrameworkConfigurationCapSrc"],
+    product_variables: {
+        debuggable: {
+            cmd: "sed -e 's|TuningAllowed=\"false\"|TuningAllowed=\"true\" ServerPort=\"unix:///dev/socket/audioserver/policy_debug\"|g' <$(in) > $(out)",
+        },
+    },
+    cmd: "cp -f $(in) $(out)",
+}
+
+genrule {
+    name: "buildaidlcommontypesstructure_gen",
+    defaults: ["buildcommontypesstructurerule"],
+    out: ["CapSubsystem-CommonTypes.xml"],
+}
+
+filegroup {
+    name: "ParameterFrameworkConfigurationCapSrc",
+    srcs: ["etc/ParameterFrameworkConfigurationCap.xml"],
+}
+
+filegroup {
+    name: "cap_product_strategies_structure",
+    srcs: ["etc/Structure/CapProductStrategies.xml"],
+}
+
+filegroup {
+    name: "CapSubsystem",
+    srcs: ["etc/Structure/CapSubsystem.xml"],
+}
+
+filegroup {
+    name: "aidl_common_types_structure_template",
+    srcs: ["etc/Structure/CapSubsystem-CommonTypes.xml.in"],
+}
+
+filegroup {
+    name: "CapClass",
+    srcs: ["etc/Structure/CapClass.xml"],
+}
diff --git a/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml b/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml
new file mode 100644
index 0000000..bac7a25
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/ParameterFrameworkConfigurationCap.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ParameterFrameworkConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    SystemClassName="Policy" TuningAllowed="false">
+
+    <SubsystemPlugins>
+        <Location Folder="">
+            <Plugin Name="libpolicy-subsystem.so"/>
+        </Location>
+    </SubsystemPlugins>
+    <StructureDescriptionFileLocation Path="Structure/Policy/CapClass.xml"/>
+</ParameterFrameworkConfiguration>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml
new file mode 100644
index 0000000..e233673
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapClass.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<SystemClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="../../Schemas/SystemClass.xsd" Name="Policy">
+    <SubsystemInclude Path="CapSubsystem.xml"/>
+</SystemClass>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml
new file mode 100644
index 0000000..61f056a
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapProductStrategies.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xi="http://www.w3.org/2001/XInclude"
+              xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+  <!-- This structure is expected to be in the system partition and provisionned a maximum
+       allowed strategies to be used by vendor. -->
+  <ComponentType Name="ProductStrategies" Description="">
+    <Component Name="vx_1000" Type="ProductStrategy" Mapping="Identifier:1000,Name:vx_1000"/>
+    <Component Name="vx_1001" Type="ProductStrategy" Mapping="Identifier:1001,Name:vx_1001"/>
+    <Component Name="vx_1002" Type="ProductStrategy" Mapping="Identifier:1002,Name:vx_1002"/>
+    <Component Name="vx_1003" Type="ProductStrategy" Mapping="Identifier:1003,Name:vx_1003"/>
+    <Component Name="vx_1004" Type="ProductStrategy" Mapping="Identifier:1004,Name:vx_1004"/>
+    <Component Name="vx_1005" Type="ProductStrategy" Mapping="Identifier:1005,Name:vx_1005"/>
+    <Component Name="vx_1006" Type="ProductStrategy" Mapping="Identifier:1006,Name:vx_1006"/>
+    <Component Name="vx_1007" Type="ProductStrategy" Mapping="Identifier:1007,Name:vx_1007"/>
+    <Component Name="vx_1008" Type="ProductStrategy" Mapping="Identifier:1008,Name:vx_1008"/>
+    <Component Name="vx_1009" Type="ProductStrategy" Mapping="Identifier:1009,Name:vx_1009"/>
+    <Component Name="vx_1010" Type="ProductStrategy" Mapping="Identifier:1010,Name:vx_1010"/>
+    <Component Name="vx_1011" Type="ProductStrategy" Mapping="Identifier:1011,Name:vx_1011"/>
+    <Component Name="vx_1012" Type="ProductStrategy" Mapping="Identifier:1012,Name:vx_1012"/>
+    <Component Name="vx_1013" Type="ProductStrategy" Mapping="Identifier:1013,Name:vx_1013"/>
+    <Component Name="vx_1014" Type="ProductStrategy" Mapping="Identifier:1014,Name:vx_1014"/>
+    <Component Name="vx_1015" Type="ProductStrategy" Mapping="Identifier:1015,Name:vx_1015"/>
+    <Component Name="vx_1016" Type="ProductStrategy" Mapping="Identifier:1016,Name:vx_1016"/>
+    <Component Name="vx_1017" Type="ProductStrategy" Mapping="Identifier:1017,Name:vx_1017"/>
+    <Component Name="vx_1018" Type="ProductStrategy" Mapping="Identifier:1018,Name:vx_1018"/>
+    <Component Name="vx_1019" Type="ProductStrategy" Mapping="Identifier:1019,Name:vx_1019"/>
+    <Component Name="vx_1020" Type="ProductStrategy" Mapping="Identifier:1020,Name:vx_1020"/>
+    <Component Name="vx_1021" Type="ProductStrategy" Mapping="Identifier:1021,Name:vx_1021"/>
+    <Component Name="vx_1022" Type="ProductStrategy" Mapping="Identifier:1022,Name:vx_1022"/>
+    <Component Name="vx_1023" Type="ProductStrategy" Mapping="Identifier:1023,Name:vx_1023"/>
+    <Component Name="vx_1024" Type="ProductStrategy" Mapping="Identifier:1024,Name:vx_1024"/>
+    <Component Name="vx_1025" Type="ProductStrategy" Mapping="Identifier:1025,Name:vx_1025"/>
+    <Component Name="vx_1026" Type="ProductStrategy" Mapping="Identifier:1026,Name:vx_1026"/>
+    <Component Name="vx_1027" Type="ProductStrategy" Mapping="Identifier:1027,Name:vx_1027"/>
+    <Component Name="vx_1028" Type="ProductStrategy" Mapping="Identifier:1028,Name:vx_1028"/>
+    <Component Name="vx_1029" Type="ProductStrategy" Mapping="Identifier:1029,Name:vx_1029"/>
+    <Component Name="vx_1030" Type="ProductStrategy" Mapping="Identifier:1030,Name:vx_1030"/>
+    <Component Name="vx_1031" Type="ProductStrategy" Mapping="Identifier:1031,Name:vx_1031"/>
+    <Component Name="vx_1032" Type="ProductStrategy" Mapping="Identifier:1032,Name:vx_1032"/>
+    <Component Name="vx_1033" Type="ProductStrategy" Mapping="Identifier:1033,Name:vx_1033"/>
+    <Component Name="vx_1034" Type="ProductStrategy" Mapping="Identifier:1034,Name:vx_1034"/>
+    <Component Name="vx_1035" Type="ProductStrategy" Mapping="Identifier:1035,Name:vx_1035"/>
+    <Component Name="vx_1036" Type="ProductStrategy" Mapping="Identifier:1036,Name:vx_1036"/>
+    <Component Name="vx_1037" Type="ProductStrategy" Mapping="Identifier:1037,Name:vx_1037"/>
+    <Component Name="vx_1038" Type="ProductStrategy" Mapping="Identifier:1038,Name:vx_1038"/>
+    <Component Name="vx_1039" Type="ProductStrategy" Mapping="Identifier:1039,Name:vx_1039"/>
+  </ComponentType>
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in
new file mode 100644
index 0000000..2c4c7b5
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem-CommonTypes.xml.in
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ComponentTypeSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xmlns:xi="http://www.w3.org/2001/XInclude"
+              xsi:noNamespaceSchemaLocation="Schemas/ComponentTypeSet.xsd">
+    <!-- Output devices definition as a bitfield for the supported devices per output
+    profile. It must match with the output device enum parameter.
+    -->
+     <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+
+     <!--#################### GLOBAL COMPONENTS END ####################-->
+
+    <!-- Automatically filled from audio-base.h file -->
+    <ComponentType Name="OutputDevicesMask" Description="64bit representation of devices">
+        <BitParameterBlock Name="mask" Size="64">
+        </BitParameterBlock>
+    </ComponentType>
+
+    <!-- Input devices definition as a bitfield for the supported devices per Input
+    profile. It must match with the Input device enum parameter.
+    -->
+    <!-- Automatically filled from audio-base.h file -->
+    <ComponentType Name="InputDevicesMask" Description="64bit representation of devices">
+        <BitParameterBlock Name="mask" Size="64">
+        </BitParameterBlock>
+    </ComponentType>
+
+    <!--#################### STREAM COMMON TYPES BEGIN ####################-->
+    <!-- Automatically filled from audio-base.h file. VolumeProfileType is associated to stream type -->
+    <ComponentType Name="VolumeProfileType">
+        <EnumParameter Name="volume_profile" Size="32">
+        </EnumParameter>
+    </ComponentType>
+
+    <ComponentType Name="Stream"  Mapping="Stream">
+        <Component Name="applicable_volume_profile" Type="VolumeProfileType"
+                   Description="Volume profile followed by a given stream type."/>
+    </ComponentType>
+
+    <!--#################### STREAM COMMON TYPES END ####################-->
+
+    <!--#################### INPUT SOURCE COMMON TYPES BEGIN ####################-->
+
+    <ComponentType Name="InputSource">
+        <Component Name="applicable_input_device" Type="InputDevicesMask"
+                   Mapping="InputSource" Description="Selected Input device"/>
+    </ComponentType>
+
+    <!--#################### INPUT SOURCE COMMON TYPES END ####################-->
+
+    <!--#################### PRODUCT STRATEGY COMMON TYPES BEGIN ####################-->
+
+    <ComponentType Name="ProductStrategy" Mapping="ProductStrategy">
+        <Component Name="selected_output_devices" Type="OutputDevicesMask"/>
+        <StringParameter Name="device_address" MaxLength="256"
+                         Description="if any, device address associated"/>
+    </ComponentType>
+
+    <!--#################### PRODUCT STRATEGY COMMON TYPES END ####################-->
+
+</ComponentTypeSet>
diff --git a/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml
new file mode 100644
index 0000000..45a0bd4
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/data/etc/Structure/CapSubsystem.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<Subsystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:xi="http://www.w3.org/2001/XInclude"
+           xsi:noNamespaceSchemaLocation="Schemas/Subsystem.xsd"
+           Name="policy" Type="Policy">
+
+    <ComponentLibrary>
+        <!--#################### GLOBAL COMPONENTS BEGIN ####################-->
+        <!-- Common Types definition -->
+        <xi:include href="CapSubsystem-CommonTypes.xml"/>
+        <xi:include href="CapProductStrategies.xml"/>
+
+
+        <!--#################### GLOBAL COMPONENTS END ####################-->
+
+        <!--#################### STREAM BEGIN ####################-->
+
+        <ComponentType Name="Streams" Description="associated to audio_stream_type_t definition">
+            <Component Name="voice_call" Type="Stream" Mapping="Name:AUDIO_STREAM_VOICE_CALL"/>
+            <Component Name="system" Type="Stream" Mapping="Name:AUDIO_STREAM_SYSTEM"/>
+            <Component Name="ring" Type="Stream" Mapping="Name:AUDIO_STREAM_RING"/>
+            <Component Name="music" Type="Stream" Mapping="Name:AUDIO_STREAM_MUSIC"/>
+            <Component Name="alarm" Type="Stream" Mapping="Name:AUDIO_STREAM_ALARM"/>
+            <Component Name="notification" Type="Stream" Mapping="Name:AUDIO_STREAM_NOTIFICATION"/>
+            <Component Name="bluetooth_sco" Type="Stream" Mapping="Name:AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <Component Name="enforced_audible" Type="Stream" Mapping="Name:AUDIO_STREAM_ENFORCED_AUDIBLE"
+                       Description="Sounds that cannot be muted by user and must be routed to speaker"/>
+            <Component Name="dtmf" Type="Stream" Mapping="Name:AUDIO_STREAM_DTMF"/>
+            <Component Name="tts" Type="Stream" Mapping="Name:AUDIO_STREAM_TTS"
+                             Description="Transmitted Through Speaker. Plays over speaker only, silent on other devices"/>
+            <Component Name="accessibility" Type="Stream" Mapping="Name:AUDIO_STREAM_ACCESSIBILITY"
+                             Description="For accessibility talk back prompts"/>
+            <Component Name="assistant" Type="Stream" Mapping="Name:AUDIO_STREAM_ASSISTANT"
+                             Description="used by a virtual assistant like Google Assistant, Bixby, etc."/>
+            <Component Name="rerouting" Type="Stream" Mapping="Name:AUDIO_STREAM_REROUTING"
+                             Description="For dynamic policy output mixes"/>
+            <Component Name="patch" Type="Stream" Mapping="Name:AUDIO_STREAM_PATCH"
+                             Description="For internal audio flinger tracks. Fixed volume"/>
+        </ComponentType>
+
+        <!--#################### STREAM END ####################-->
+
+        <!--#################### INPUT SOURCE BEGIN ####################-->
+
+        <ComponentType Name="InputSources" Description="associated to audio_source_t definition,
+                             identifier mapping must match the value of the enum">
+            <Component Name="default" Type="InputSource" Mapping="Name:AUDIO_SOURCE_DEFAULT"/>
+            <Component Name="mic" Type="InputSource" Mapping="Name:AUDIO_SOURCE_MIC"/>
+            <Component Name="voice_uplink" Type="InputSource"
+                                           Mapping="Name:AUDIO_SOURCE_VOICE_UPLINK"/>
+            <Component Name="voice_downlink" Type="InputSource"
+                                             Mapping="Name:AUDIO_SOURCE_VOICE_DOWNLINK"/>
+            <Component Name="voice_call" Type="InputSource"
+                                         Mapping="Name:AUDIO_SOURCE_VOICE_CALL"/>
+            <Component Name="camcorder" Type="InputSource" Mapping="Name:AUDIO_SOURCE_CAMCORDER"/>
+            <Component Name="voice_recognition" Type="InputSource"
+                                                Mapping="Name:AUDIO_SOURCE_VOICE_RECOGNITION"/>
+            <Component Name="voice_communication" Type="InputSource"
+                                                  Mapping="Name:AUDIO_SOURCE_VOICE_COMMUNICATION"/>
+            <Component Name="remote_submix" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_REMOTE_SUBMIX"/>
+            <Component Name="unprocessed" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_UNPROCESSED"/>
+            <Component Name="voice_performance" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_VOICE_PERFORMANCE"/>
+            <Component Name="echo_reference" Type="InputSource"
+                                            Mapping="Name:AUDIO_SOURCE_ECHO_REFERENCE"/>
+            <Component Name="fm_tuner" Type="InputSource" Mapping="Name:AUDIO_SOURCE_FM_TUNER"/>
+            <Component Name="hotword" Type="InputSource" Mapping="Name:AUDIO_SOURCE_HOTWORD"/>
+        </ComponentType>
+        <!--#################### INPUT SOURCE END ####################-->
+    </ComponentLibrary>
+
+    <InstanceDefinition>
+        <Component Name="streams" Type="Streams"/>
+        <Component Name="input_sources" Type="InputSources"/>
+        <Component Name="product_strategies" Type="ProductStrategies"/>
+    </InstanceDefinition>
+</Subsystem>
diff --git a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
index 9fd8b8e..e0b7210 100644
--- a/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
+++ b/services/audiopolicy/engineconfigurable/interface/AudioPolicyPluginInterface.h
@@ -98,7 +98,8 @@
     virtual bool setDeviceTypesForProductStrategy(product_strategy_t strategy,
                                                   uint64_t devices) = 0;
 
-    virtual product_strategy_t getProductStrategyByName(const std::string &address) = 0;
+    virtual product_strategy_t getProductStrategyByName(const std::string &name) = 0;
+    virtual std::string getProductStrategyName(product_strategy_t id) const = 0;
 
 protected:
     virtual ~AudioPolicyPluginInterface() {}
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
index 7fe111f..e4f44d5 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/Android.bp
@@ -50,6 +50,7 @@
 genrule {
     name: "buildcommontypesstructure_gen",
     defaults: ["buildcommontypesstructurerule"],
+    out: ["PolicySubsystem-CommonTypes.xml"],
 }
 
 filegroup {
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
index 8bd7f66..bf5767d 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/PolicySubsystem.cpp
@@ -72,7 +72,7 @@
         );
     addSubsystemObjectFactory(
         new TSubsystemObjectFactory<ProductStrategy>(
-            mProductStrategyComponentName, (1 << MappingKeyName))
+            mProductStrategyComponentName, (1 << MappingKeyName) | (1 << MappingKeyIdentifier))
         );
 }
 
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
index ebd9456..06efbf28 100644
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/ProductStrategy.cpp
@@ -18,10 +18,7 @@
 #include "PolicyMappingKeys.h"
 #include "PolicySubsystem.h"
 
-using std::string;
-using android::product_strategy_t;
-
-ProductStrategy::ProductStrategy(const string &mappingValue,
+ProductStrategy::ProductStrategy(const std::string &mappingValue,
                    CInstanceConfigurableElement *instanceConfigurableElement,
                    const CMappingContext &context,
                    core::log::Logger& logger)
@@ -30,26 +27,32 @@
                                 mappingValue,
                                 MappingKeyAmend1,
                                 (MappingKeyAmendEnd - MappingKeyAmend1 + 1),
-                                context)
-{
-    std::string name(context.getItem(MappingKeyName));
+                                context) {
+
+    size_t id = context.getItemAsInteger(MappingKeyIdentifier);
+    std::string nameFromStructure(context.getItem(MappingKeyName));
 
     ALOG_ASSERT(instanceConfigurableElement != nullptr, "Invalid Configurable Element");
     mPolicySubsystem = static_cast<const PolicySubsystem *>(
-                instanceConfigurableElement->getBelongingSubsystem());
+            instanceConfigurableElement->getBelongingSubsystem());
     ALOG_ASSERT(mPolicySubsystem != nullptr, "Invalid Policy Subsystem");
 
     mPolicyPluginInterface = mPolicySubsystem->getPolicyPluginInterface();
     ALOG_ASSERT(mPolicyPluginInterface != nullptr, "Invalid Policy Plugin Interface");
 
-    mId = mPolicyPluginInterface->getProductStrategyByName(name);
+    mId = static_cast<android::product_strategy_t>(id);
+    std::string name = mPolicyPluginInterface->getProductStrategyName(mId);
+    if (name.empty()) {
+        name = nameFromStructure;
+        mId = mPolicyPluginInterface->getProductStrategyByName(name);
+    }
 
     ALOG_ASSERT(mId != PRODUCT_STRATEGY_INVALID, "Product Strategy %s not found", name.c_str());
 
     ALOGE("Product Strategy %s added", name.c_str());
 }
 
-bool ProductStrategy::sendToHW(string & /*error*/)
+bool ProductStrategy::sendToHW(std::string & /*error*/)
 {
     Device deviceParams;
     blackboardRead(&deviceParams, sizeof(deviceParams));
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index ccd4316..45da7b0 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -71,27 +71,75 @@
 }
 
 status_t Engine::loadFromHalConfigWithFallback(
-        const media::audio::common::AudioHalEngineConfig& config __unused) {
-    // b/242678729. Need to implement for the configurable engine.
-    return INVALID_OPERATION;
-}
+        const media::audio::common::AudioHalEngineConfig& aidlConfig) {
 
-status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
-{
-    status_t loadResult = loadAudioPolicyEngineConfig(xmlFilePath);
-    if (loadResult < 0) {
-        ALOGE("Policy Engine configuration is invalid.");
+    auto capResult = capEngineConfig::convert(aidlConfig);
+    if (capResult.parsedConfig == nullptr) {
+        ALOGE("%s CapEngine Config invalid", __func__);
+        return BAD_VALUE;
     }
-    return loadResult;
-}
-
-status_t Engine::initCheck()
-{
+    status_t ret = loadWithFallback(aidlConfig);
+    if (ret != NO_ERROR) {
+        return ret;
+    }
+    auto loadCriteria= [this](const auto& capCriteria) {
+        for (auto& capCriterion : capCriteria) {
+            mPolicyParameterMgr->addCriterion(capCriterion.criterion.name,
+                    capCriterion.criterionType.isInclusive,
+                    capCriterion.criterionType.valuePairs,
+                    capCriterion.criterion.defaultLiteralValue);
+        }
+    };
+    loadCriteria(capResult.parsedConfig->capCriteria);
     std::string error;
     if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
         ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
         return NO_INIT;
     }
+    return mPolicyParameterMgr->setConfiguration(capResult);
+}
+
+status_t Engine::loadFromXmlConfigWithFallback(const std::string& xmlFilePath)
+{
+    status_t status = loadWithFallback(xmlFilePath);
+    std::string error;
+    if (mPolicyParameterMgr == nullptr || mPolicyParameterMgr->start(error) != NO_ERROR) {
+        ALOGE("%s: could not start Policy PFW: %s", __FUNCTION__, error.c_str());
+        return NO_INIT;
+    }
+    return status;
+}
+
+template<typename T>
+status_t Engine::loadWithFallback(const T& configSource) {
+    auto result = EngineBase::loadAudioPolicyEngineConfig(configSource);
+    ALOGE_IF(result.nbSkippedElement != 0,
+             "Policy Engine configuration is partially invalid, skipped %zu elements",
+             result.nbSkippedElement);
+
+    auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
+        for (auto& criterion : configCriteria) {
+            engineConfig::CriterionType criterionType;
+            for (auto &configCriterionType : configCriterionTypes) {
+                if (configCriterionType.name == criterion.typeName) {
+                    criterionType = configCriterionType;
+                    break;
+                }
+            }
+            ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
+                        criterion.name.c_str());
+            mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
+                                              criterionType.valuePairs,
+                                              criterion.defaultLiteralValue);
+        }
+    };
+
+    loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
+    return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
+}
+
+status_t Engine::initCheck()
+{
     return EngineBase::initCheck();
 }
 
@@ -199,32 +247,6 @@
     return EngineBase::setDeviceConnectionState(device, state);
 }
 
-status_t Engine::loadAudioPolicyEngineConfig(const std::string& xmlFilePath)
-{
-    auto result = EngineBase::loadAudioPolicyEngineConfig(xmlFilePath);
-
-    // Custom XML Parsing
-    auto loadCriteria= [this](const auto& configCriteria, const auto& configCriterionTypes) {
-        for (auto& criterion : configCriteria) {
-            engineConfig::CriterionType criterionType;
-            for (auto &configCriterionType : configCriterionTypes) {
-                if (configCriterionType.name == criterion.typeName) {
-                    criterionType = configCriterionType;
-                    break;
-                }
-            }
-            ALOG_ASSERT(not criterionType.name.empty(), "Invalid criterion type for %s",
-                        criterion.name.c_str());
-            mPolicyParameterMgr->addCriterion(criterion.name, criterionType.isInclusive,
-                                              criterionType.valuePairs,
-                                              criterion.defaultLiteralValue);
-        }
-    };
-
-    loadCriteria(result.parsedConfig->criteria, result.parsedConfig->criterionTypes);
-    return result.nbSkippedElement == 0? NO_ERROR : BAD_VALUE;
-}
-
 status_t Engine::setDevicesRoleForStrategy(product_strategy_t strategy, device_role_t role,
                                            const AudioDeviceTypeAddrVector &devices)
 {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.h b/services/audiopolicy/engineconfigurable/src/Engine.h
index 4f3e620..d9ebbe7 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.h
+++ b/services/audiopolicy/engineconfigurable/src/Engine.h
@@ -16,10 +16,11 @@
 
 #pragma once
 
-#include "EngineBase.h"
-#include <EngineInterface.h>
-#include <AudioPolicyPluginInterface.h>
 #include "Collection.h"
+#include "EngineBase.h"
+#include <AudioPolicyPluginInterface.h>
+#include <CapEngineConfig.h>
+#include <EngineInterface.h>
 
 namespace android {
 class AudioPolicyManagerObserver;
@@ -107,8 +108,14 @@
     {
         return EngineBase::getProductStrategyByName(name);
     }
+    std::string getProductStrategyName(product_strategy_t id) const override {
+        return EngineBase::getProductStrategyName(id);
+    }
 
 private:
+    template<typename T>
+    status_t loadWithFallback(const T& configSource);
+
     android::status_t disableDevicesForStrategy(product_strategy_t strategy,
             const DeviceVector &devicesToDisable);
     void enableDevicesForStrategy(product_strategy_t strategy, const DeviceVector &devicesToEnable);
@@ -140,8 +147,6 @@
     template <typename Property, typename Key>
     bool setPropertyForKey(const Property &property, const Key &key);
 
-    status_t loadAudioPolicyEngineConfig(const std::string& xmlFilePath);
-
     DeviceVector getCachedDevices(product_strategy_t ps) const;
 
     ///
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index d1fb2fb..7ae124c 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -23,7 +23,7 @@
 }
 
 //##################################################################################################
-// Tools for audio policy engine criterion type configuration file
+// Legacy tools for audio policy engine criterion type configuration file
 //
 python_binary_host {
     name: "buildPolicyCriterionTypes",
@@ -57,6 +57,40 @@
 }
 
 //##################################################################################################
+// Tools for audio policy engine criterion type configuration file
+//
+python_binary_host {
+    name: "capBuildPolicyCriterionTypes",
+    main: "capBuildPolicyCriterionTypes.py",
+    srcs: [
+        "capBuildPolicyCriterionTypes.py",
+    ],
+}
+
+genrule_defaults {
+    name: "capbuildpolicycriteriontypesrule",
+    tools: ["capBuildPolicyCriterionTypes"],
+    cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
+        "cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
+        "$(location capBuildPolicyCriterionTypes) " +
+        " --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
+        " --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
+        "--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
+        "--criteriontypes $(location :audio_policy_engine_aidl_criterion_types_template) " +
+        "--outputfile $(out)",
+    srcs: [
+        // The commented inputs must be provided to use this genrule_defaults
+        // @todo uncomment if 1428659 is merged":android_audio_base_header_file",
+        ":audio_policy_engine_aidl_criterion_types_template",
+        ":libaudio_system_audio_base",
+        ":libaudio_system_audio_common_base",
+        // ":audio_policy_configuration_top_file",
+        // ":audio_policy_configuration_files",
+    ],
+    out: ["audio_policy_engine_criterion_types.xml"],
+}
+
+//##################################################################################################
 // Tools for audio policy engine parameter framework configurable domains
 //
 python_binary_host {
@@ -84,6 +118,7 @@
     cmd: "mkdir -p $(genDir)/Structure/Policy && " +
         "cp $(locations :audio_policy_pfw_structure_files) $(genDir)/Structure/Policy && " +
         "cp $(location :audio_policy_pfw_toplevel) $(genDir)/top_level && " +
+        "sed -i -e 's|TuningAllowed=\"false\"|TuningAllowed=\"true\" ServerPort=\"unix:///dev/socket/audioserver/policy_debug\"|g' $(genDir)/top_level &&" +
         "$(location domainGeneratorPolicy) " +
         "--validate " +
         "--domain-generator-tool $(location domainGeneratorConnector) " +
@@ -106,7 +141,7 @@
 }
 
 //##################################################################################################
-// Tools for policy parameter-framework product strategies structure file generation
+// Legacy tools for policy parameter-framework product strategies structure file generation
 //
 python_binary_host {
     name: "buildStrategiesStructureFile",
@@ -154,5 +189,4 @@
         ":common_types_structure_template",
         ":libaudio_system_audio_base",
     ],
-    out: ["PolicySubsystem-CommonTypes.xml"],
 }
diff --git a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
index f69d346..6eabc57 100755
--- a/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
+++ b/services/audiopolicy/engineconfigurable/tools/buildStrategiesStructureFile.py
@@ -75,7 +75,7 @@
     strategy_components = strategies_root.find('ComponentType')
 
     for strategy_name in strategies:
-        context_mapping = "".join(map(str, ["Name:", strategy_name]))
+        context_mapping = "".join(map(str, ["Identifier:-1,Name:", strategy_name]))
         strategy_pfw_name = strategy_name.replace('STRATEGY_', '').lower()
         ET.SubElement(strategy_components, "Component",
                       Name=strategy_pfw_name, Type="ProductStrategy",
diff --git a/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py b/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py
new file mode 100755
index 0000000..b873830
--- /dev/null
+++ b/services/audiopolicy/engineconfigurable/tools/capBuildPolicyCriterionTypes.py
@@ -0,0 +1,368 @@
+#!/usr/bin/python3
+
+#
+# Copyright 2018, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import argparse
+import re
+import sys
+import os
+import logging
+import xml.etree.ElementTree as ET
+import xml.etree.ElementInclude as EI
+import xml.dom.minidom as MINIDOM
+from collections import OrderedDict
+
+#
+# Helper script that helps to feed at build time the XML criterion types file used by
+# the engineconfigurable to start the parameter-framework.
+# It prevents to fill them manually and avoid divergences with android.
+#
+# The Device Types criterion types are fed from audio-base.h file with the option
+#           --androidaudiobaseheader <path/to/android/audio/base/file/audio-base.h>
+#
+# The Device Addresses criterion types are fed from the audio policy configuration file
+# in order to discover all the devices for which the address matter.
+#           --audiopolicyconfigurationfile <path/to/audio_policy_configuration.xml>
+#
+# The reference file of criterion types must also be set as an input of the script:
+#           --criteriontypes <path/to/criterion/file/audio_criterion_types.xml.in>
+#
+# At last, the output of the script shall be set also:
+#           --outputfile <path/to/out/vendor/etc/audio_criterion_types.xml>
+#
+
+def parseArgs():
+    argparser = argparse.ArgumentParser(description="Parameter-Framework XML \
+                                        audio criterion type file generator.\n\
+                                        Exit with the number of (recoverable or not) \
+                                        error that occurred.")
+    argparser.add_argument('--androidaudiobaseheader',
+                           help="Android Audio Base C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--androidaudiocommonbaseheader',
+                           help="Android Audio CommonBase C header file, Mandatory.",
+                           metavar="ANDROID_AUDIO_COMMON_BASE_HEADER",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--audiopolicyconfigurationfile',
+                           help="Android Audio Policy Configuration file, Mandatory.",
+                           metavar="(AUDIO_POLICY_CONFIGURATION_FILE)",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--criteriontypes',
+                           help="Criterion types XML base file, in \
+                           '<criterion_types> \
+                               <criterion_type name="" type=<inclusive|exclusive> \
+                               values=<value1,value2,...>/>' \
+                           format. Mandatory.",
+                           metavar="CRITERION_TYPE_FILE",
+                           type=argparse.FileType('r'),
+                           required=True)
+    argparser.add_argument('--outputfile',
+                           help="Criterion types outputfile file. Mandatory.",
+                           metavar="CRITERION_TYPE_OUTPUT_FILE",
+                           type=argparse.FileType('w'),
+                           required=True)
+    argparser.add_argument('--verbose',
+                           action='store_true')
+
+    return argparser.parse_args()
+
+
+output_devices_type_value = {}
+input_devices_type_value = {}
+
+def generateXmlCriterionTypesFile(criterionTypes, addressCriteria, criterionTypesFile, outputFile):
+
+    logging.info("Importing criterionTypesFile {}".format(criterionTypesFile))
+    criterion_types_in_tree = ET.parse(criterionTypesFile)
+
+    criterion_types_root = criterion_types_in_tree.getroot()
+
+    for criterion_name, values_dict in criterionTypes.items():
+        for criterion_type in criterion_types_root.findall('criterion_type'):
+            if criterion_type.get('name') == criterion_name:
+                values_node = ET.SubElement(criterion_type, "values")
+                ordered_values = OrderedDict(sorted(values_dict.items(), key=lambda x: x[1]))
+                for key, value in ordered_values.items():
+                    value_node = ET.SubElement(values_node, "value")
+                    value_node.set('numerical', str(value))
+                    value_node.set('literal', key)
+
+                    if criterion_type.get('name') == "OutputDevicesMaskType":
+                        value_node.set('android_type', output_devices_type_value[key])
+                    if criterion_type.get('name') == "InputDevicesMaskType":
+                        value_node.set('android_type', input_devices_type_value[key])
+
+    if addressCriteria:
+        for criterion_name, values_list in addressCriteria.items():
+            for criterion_type in criterion_types_root.findall('criterion_type'):
+                if criterion_type.get('name') == criterion_name:
+                    index = 0
+                    existing_values_node = criterion_type.find("values")
+                    if existing_values_node is not None:
+                        for existing_value in existing_values_node.findall('value'):
+                            if existing_value.get('numerical') == str(1 << index):
+                                index += 1
+                        values_node = existing_values_node
+                    else:
+                        values_node = ET.SubElement(criterion_type, "values")
+
+                    for value in values_list:
+                        value_node = ET.SubElement(values_node, "value", literal=value)
+                        value_node.set('numerical', str(1 << index))
+                        index += 1
+
+    xmlstr = ET.tostring(criterion_types_root, encoding='utf8', method='xml')
+    reparsed = MINIDOM.parseString(xmlstr)
+    prettyXmlStr = reparsed.toprettyxml(newl='\r\n')
+    prettyXmlStr = os.linesep.join([s for s in prettyXmlStr.splitlines() if s.strip()])
+    outputFile.write(prettyXmlStr)
+
+def capitalizeLine(line):
+    return ' '.join((w.capitalize() for w in line.split(' ')))
+
+
+#
+# Parse the audio policy configuration file and output a dictionary of device criteria addresses
+#
+def parseAndroidAudioPolicyConfigurationFile(audiopolicyconfigurationfile):
+
+    logging.info("Checking Audio Policy Configuration file {}".format(audiopolicyconfigurationfile))
+    #
+    # extract all devices addresses from audio policy configuration file
+    #
+    address_criteria_mapping_table = {
+        'sink' : "OutputDevicesAddressesType",
+        'source' : "InputDevicesAddressesType"}
+
+    address_criteria = {
+        'OutputDevicesAddressesType' : [],
+        'InputDevicesAddressesType' : []}
+
+    old_working_dir = os.getcwd()
+    print("Current working directory %s" % old_working_dir)
+
+    new_dir = os.path.join(old_working_dir, audiopolicyconfigurationfile.name)
+
+    policy_in_tree = ET.parse(audiopolicyconfigurationfile)
+    os.chdir(os.path.dirname(os.path.normpath(new_dir)))
+
+    print("new working directory %s" % os.getcwd())
+
+    policy_root = policy_in_tree.getroot()
+    EI.include(policy_root)
+
+    os.chdir(old_working_dir)
+
+    for device in policy_root.iter('devicePort'):
+        for key in address_criteria_mapping_table.keys():
+            if device.get('role') == key and device.get('address'):
+                logging.info("{}: <{}>".format(key, device.get('address')))
+                address_criteria[address_criteria_mapping_table[key]].append(device.get('address'))
+
+    for criteria in address_criteria:
+        values = ','.join(address_criteria[criteria])
+        logging.info("{}: <{}>".format(criteria, values))
+
+    return address_criteria
+
+#
+# Parse the audio-base.h file and output a dictionary of android dependent criterion types:
+#   -Android Mode
+#   -Output devices type
+#   -Input devices type
+#
+def parseAndroidAudioFile(androidaudiobaseheaderFile, androidaudiocommonbaseheaderFile):
+    #
+    # Adaptation table between Android Enumeration prefix and Audio PFW Criterion type names
+    #
+    criterion_mapping_table = {
+        'HAL_AUDIO_MODE' : "AndroidModeType",
+        'AUDIO_DEVICE_OUT' : "OutputDevicesMaskType",
+        'AUDIO_DEVICE_IN' : "InputDevicesMaskType"}
+
+    all_criteria = {
+        'AndroidModeType' : {},
+        'OutputDevicesMaskType' : {},
+        'InputDevicesMaskType' : {}}
+
+    #
+    # _CNT, _MAX, _ALL and _NONE are prohibited values as ther are just helpers for enum users.
+    #
+    ignored_values = ['CNT', 'MAX', 'ALL', 'NONE']
+
+    multi_bit_outputdevice_shift = 32
+    multi_bit_inputdevice_shift = 32
+
+    criteria_pattern = re.compile(
+        r"\s*V\((?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+        r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*,\s*" \
+        r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+    logging.info("Checking Android Header file {}".format(androidaudiobaseheaderFile))
+
+    for line_number, line in enumerate(androidaudiobaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiobaseheaderFile.name, line_number, line))
+
+            criterion_name = criterion_mapping_table[match.groupdict()['type']]
+            criterion_literal = ''.join(match.groupdict()['literal'])
+            criterion_numerical_value = match.groupdict()['values']
+
+            if criterion_name == "InputDevicesMaskType":
+                # Remove ambient and in_communication since they were deprecated
+                logging.info("Remove deprecated device {}".format(criterion_literal))
+                if criterion_literal == "AMBIENT" or criterion_literal == "COMMUNICATION":
+                    logging.info("Remove deprecated device {}".format(criterion_literal))
+                    continue
+                # for AUDIO_DEVICE_IN: rename default to stub
+                elif criterion_literal == "DEFAULT":
+                    criterion_numerical_value = str(int("0x40000000", 0))
+                    input_devices_type_value[criterion_literal] = "0xC0000000"
+                else:
+                    try:
+                        string_int = int(criterion_numerical_value, 0)
+                        # Append AUDIO_DEVICE_IN for android type tag
+                        input_devices_type_value[criterion_literal] = hex(string_int | 2147483648)
+
+                        num_bits = bin(string_int).count("1")
+                        if num_bits > 1:
+                            logging.info("The value {}:{} is for criterion {} binary rep {} has {} bits sets"
+                                .format(criterion_numerical_value, criterion_literal, criterion_name, bin(string_int), num_bits))
+                            string_int = 2**multi_bit_inputdevice_shift
+                            logging.info("new val assigned is {} {}" .format(string_int, bin(string_int)))
+                            multi_bit_inputdevice_shift += 1
+                            criterion_numerical_value = str(string_int)
+
+                    except ValueError:
+                        # Handle the exception
+                        logging.info("value {}:{} for criterion {} is not a number, ignoring"
+                            .format(criterion_numerical_value, criterion_literal, criterion_name))
+                        continue
+
+            if criterion_name == "OutputDevicesMaskType":
+                if criterion_literal == "DEFAULT":
+                    criterion_numerical_value = str(int("0x40000000", 0))
+                    output_devices_type_value[criterion_literal] = "0x40000000"
+                else:
+                    try:
+                        string_int = int(criterion_numerical_value, 0)
+                        output_devices_type_value[criterion_literal] = criterion_numerical_value
+
+                        num_bits = bin(string_int).count("1")
+                        if num_bits > 1:
+                            logging.info("The value {}:{} is for criterion {} binary rep {} has {} bits sets"
+                                .format(criterion_numerical_value, criterion_literal, criterion_name, bin(string_int), num_bits))
+                            string_int = 2**multi_bit_outputdevice_shift
+                            logging.info("new val assigned is {} {}" .format(string_int, bin(string_int)))
+                            multi_bit_outputdevice_shift += 1
+                            criterion_numerical_value = str(string_int)
+
+                    except ValueError:
+                        # Handle the exception
+                        logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+                            .format(criterion_numerical_value, criterion_literal, criterion_name))
+                        continue
+
+            try:
+                string_int = int(criterion_numerical_value, 0)
+
+            except ValueError:
+                # Handle the exception
+                logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+                    .format(criterion_numerical_value, criterion_literal, criterion_name))
+                continue
+
+            # Remove duplicated numerical values
+            if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+                logging.info("criterion {} duplicated values:".format(criterion_name))
+                logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+                logging.info("KEEPING LATEST")
+                for key in list(all_criteria[criterion_name]):
+                    if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+                        del all_criteria[criterion_name][key]
+
+            all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+            logging.debug("type:{},".format(criterion_name))
+            logging.debug("iteral:{},".format(criterion_literal))
+            logging.debug("values:{}.".format(criterion_numerical_value))
+
+    logging.info("Checking Android Common Header file {}".format(androidaudiocommonbaseheaderFile))
+
+    criteria_pattern = re.compile(
+        r"\s*(?P<type>(?:"+'|'.join(criterion_mapping_table.keys()) + "))_" \
+        r"(?P<literal>(?!" + '|'.join(ignored_values) + ")\w*)\s*=\s*" \
+        r"(?:AUDIO_DEVICE_BIT_IN \| )?(?P<values>(?:0[xX])?[0-9a-fA-F]+|[0-9]+)")
+
+    for line_number, line in enumerate(androidaudiocommonbaseheaderFile):
+        match = criteria_pattern.match(line)
+        if match:
+            logging.debug("The following line is VALID: {}:{}\n{}".format(
+                androidaudiocommonbaseheaderFile.name, line_number, line))
+
+            criterion_name = criterion_mapping_table[match.groupdict()['type']]
+            criterion_literal = ''.join(match.groupdict()['literal'])
+            criterion_numerical_value = match.groupdict()['values']
+
+            try:
+                string_int = int(criterion_numerical_value, 0)
+            except ValueError:
+                # Handle the exception
+                logging.info("The value {}:{} is for criterion {} is not a number, ignoring"
+                    .format(criterion_numerical_value, criterion_literal, criterion_name))
+                continue
+
+            # Remove duplicated numerical values
+            if int(criterion_numerical_value, 0) in all_criteria[criterion_name].values():
+                logging.info("criterion {} duplicated values:".format(criterion_name))
+                logging.info("{}:{}".format(criterion_numerical_value, criterion_literal))
+                logging.info("KEEPING LATEST")
+                for key in list(all_criteria[criterion_name]):
+                    if all_criteria[criterion_name][key] == int(criterion_numerical_value, 0):
+                        del all_criteria[criterion_name][key]
+
+            all_criteria[criterion_name][criterion_literal] = int(criterion_numerical_value, 0)
+
+            logging.debug("type:{},".format(criterion_name))
+            logging.debug("iteral:{},".format(criterion_literal))
+            logging.debug("values:{}.".format(criterion_numerical_value))
+
+    return all_criteria
+
+
+def main():
+    logging.root.setLevel(logging.INFO)
+    args = parseArgs()
+
+    all_criteria = parseAndroidAudioFile(args.androidaudiobaseheader,
+                                         args.androidaudiocommonbaseheader)
+
+    address_criteria = parseAndroidAudioPolicyConfigurationFile(args.audiopolicyconfigurationfile)
+
+    criterion_types = args.criteriontypes
+
+    generateXmlCriterionTypesFile(all_criteria, address_criteria, criterion_types, args.outputfile)
+
+# If this file is directly executed
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/services/audiopolicy/engineconfigurable/wrapper/Android.bp b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
index 78d5fa3..506b19b 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/Android.bp
+++ b/services/audiopolicy/engineconfigurable/wrapper/Android.bp
@@ -19,10 +19,12 @@
     ],
     header_libs: [
         "libaudiofoundation_headers",
+        "libaudiopolicycapengine_config_headers",
         "libaudiopolicycommon",
         "libbase_headers",
     ],
     shared_libs: [
+        "libaudiopolicyengine_config",
         "liblog",
         "libmedia_helper",
         "libparameter",
diff --git a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
index 099d55d..0bcde8d 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
+++ b/services/audiopolicy/engineconfigurable/wrapper/ParameterManagerWrapper.cpp
@@ -18,13 +18,13 @@
 //#define LOG_NDEBUG 0
 
 #include "ParameterManagerWrapper.h"
+#include <ParameterMgrFullConnector.h>
 #include <ParameterMgrPlatformConnector.h>
 #include <SelectionCriterionTypeInterface.h>
 #include <SelectionCriterionInterface.h>
 #include <media/convert.h>
 #include <algorithm>
 #include <cutils/bitops.h>
-#include <cutils/config_utils.h>
 #include <cutils/misc.h>
 #include <fstream>
 #include <limits>
@@ -64,31 +64,10 @@
 namespace audio_policy {
 
 const char *const ParameterManagerWrapper::mPolicyPfwDefaultConfFileName =
-    "/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
+    "/etc/parameter-framework/ParameterFrameworkConfigurationCap.xml";
 const char *const ParameterManagerWrapper::mPolicyPfwVendorConfFileName =
     "/vendor/etc/parameter-framework/ParameterFrameworkConfigurationPolicy.xml";
 
-static const char *const gInputDeviceCriterionName = "AvailableInputDevices";
-static const char *const gOutputDeviceCriterionName = "AvailableOutputDevices";
-static const char *const gPhoneStateCriterionName = "TelephonyMode";
-static const char *const gOutputDeviceAddressCriterionName = "AvailableOutputDevicesAddresses";
-static const char *const gInputDeviceAddressCriterionName = "AvailableInputDevicesAddresses";
-
-/**
- * Order MUST be align with defintiion of audio_policy_force_use_t within audio_policy.h
- */
-static const char *const gForceUseCriterionTag[AUDIO_POLICY_FORCE_USE_CNT] =
-{
-    [AUDIO_POLICY_FORCE_FOR_COMMUNICATION] =        "ForceUseForCommunication",
-    [AUDIO_POLICY_FORCE_FOR_MEDIA] =                "ForceUseForMedia",
-    [AUDIO_POLICY_FORCE_FOR_RECORD] =               "ForceUseForRecord",
-    [AUDIO_POLICY_FORCE_FOR_DOCK] =                 "ForceUseForDock",
-    [AUDIO_POLICY_FORCE_FOR_SYSTEM] =               "ForceUseForSystem",
-    [AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] =    "ForceUseForHdmiSystemAudio",
-    [AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND] =     "ForceUseForEncodedSurround",
-    [AUDIO_POLICY_FORCE_FOR_VIBRATE_RINGING] =      "ForceUseForVibrateRinging"
-};
-
 template <>
 struct ParameterManagerWrapper::parameterManagerElementSupported<ISelectionCriterionInterface> {};
 template <>
@@ -100,9 +79,9 @@
 {
     // Connector
     if (access(mPolicyPfwVendorConfFileName, R_OK) == 0) {
-        mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwVendorConfFileName);
+        mPfwConnector = new CParameterMgrFullConnector(mPolicyPfwVendorConfFileName);
     } else {
-        mPfwConnector = new CParameterMgrPlatformConnector(mPolicyPfwDefaultConfFileName);
+        mPfwConnector = new CParameterMgrFullConnector(mPolicyPfwDefaultConfFileName);
     }
 
     // Logger
@@ -130,13 +109,13 @@
               std::get<2>(pair).c_str(), name.c_str());
         criterionType->addValuePair(std::get<0>(pair), std::get<2>(pair), error);
 
-        if (name == gOutputDeviceCriterionName) {
+        if (name == capEngineConfig::gOutputDeviceCriterionName) {
             ALOGV("%s: Adding mOutputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
                   __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
             audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
             mOutputDeviceToCriterionTypeMap[androidType] = std::get<0>(pair);
         }
-        if (name == gInputDeviceCriterionName) {
+        if (name == capEngineConfig::gInputDeviceCriterionName) {
             ALOGV("%s: Adding mInputDeviceToCriterionTypeMap %d %" PRIu64" for criterionType %s",
                   __func__, std::get<1>(pair), std::get<0>(pair), name.c_str());
             audio_devices_t androidType = static_cast<audio_devices_t>(std::get<1>(pair));
@@ -207,10 +186,11 @@
 
 status_t ParameterManagerWrapper::setPhoneState(audio_mode_t mode)
 {
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gPhoneStateCriterionName);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(mode))) {
@@ -223,10 +203,11 @@
 
 audio_mode_t ParameterManagerWrapper::getPhoneState() const
 {
-    const ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gPhoneStateCriterionName, mPolicyCriteria);
+    const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gPhoneStateCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gPhoneStateCriterionName);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gPhoneStateCriterionName);
         return AUDIO_MODE_NORMAL;
     }
     return static_cast<audio_mode_t>(criterion->getCriterionState());
@@ -240,10 +221,11 @@
         return BAD_VALUE;
     }
 
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gForceUseCriterionTag[usage]);
         return BAD_VALUE;
     }
     if (!isValueValidForCriterion(criterion, static_cast<int>(config))) {
@@ -260,10 +242,11 @@
     if (usage > AUDIO_POLICY_FORCE_USE_CNT) {
         return AUDIO_POLICY_FORCE_NONE;
     }
-    const ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gForceUseCriterionTag[usage], mPolicyCriteria);
+    const ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gForceUseCriterionTag[usage], mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __FUNCTION__, gForceUseCriterionTag[usage]);
+        ALOGE("%s: no criterion found for %s", __FUNCTION__,
+              capEngineConfig::gForceUseCriterionTag[usage]);
         return AUDIO_POLICY_FORCE_NONE;
     }
     return static_cast<audio_policy_forced_cfg_t>(criterion->getCriterionState());
@@ -281,8 +264,8 @@
         audio_devices_t type, const std::string &address, audio_policy_dev_state_t state)
 {
     std::string criterionName = audio_is_output_device(type) ?
-                gOutputDeviceAddressCriterionName : gInputDeviceAddressCriterionName;
-
+            capEngineConfig::gOutputDeviceAddressCriterionName :
+            capEngineConfig::gInputDeviceAddressCriterionName;
     ALOGV("%s: device with address %s %s", __FUNCTION__, address.c_str(),
           state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE? "disconnected" : "connected");
     ISelectionCriterionInterface *criterion =
@@ -311,12 +294,12 @@
     return NO_ERROR;
 }
 
-status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types)
-{
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gInputDeviceCriterionName, mPolicyCriteria);
+status_t ParameterManagerWrapper::setAvailableInputDevices(const DeviceTypeSet &types) {
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gInputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __func__, gInputDeviceCriterionName);
+        ALOGE("%s: no criterion found for %s", __func__,
+              capEngineConfig::gInputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
@@ -324,12 +307,12 @@
     return NO_ERROR;
 }
 
-status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types)
-{
-    ISelectionCriterionInterface *criterion =
-            getElement<ISelectionCriterionInterface>(gOutputDeviceCriterionName, mPolicyCriteria);
+status_t ParameterManagerWrapper::setAvailableOutputDevices(const DeviceTypeSet &types) {
+    ISelectionCriterionInterface *criterion = getElement<ISelectionCriterionInterface>(
+            capEngineConfig::gOutputDeviceCriterionName, mPolicyCriteria);
     if (criterion == NULL) {
-        ALOGE("%s: no criterion found for %s", __func__, gOutputDeviceCriterionName);
+        ALOGE("%s: no criterion found for %s", __func__,
+              capEngineConfig::gOutputDeviceCriterionName);
         return DEAD_OBJECT;
     }
     criterion->setCriterionState(convertDeviceTypesToCriterionValue(types));
@@ -344,21 +327,15 @@
 
 uint64_t ParameterManagerWrapper::convertDeviceTypeToCriterionValue(audio_devices_t type) const {
     bool isOut = audio_is_output_devices(type);
-    uint32_t typeMask = isOut ? type : (type & ~AUDIO_DEVICE_BIT_IN);
-
     const auto &adapters = isOut ? mOutputDeviceToCriterionTypeMap : mInputDeviceToCriterionTypeMap;
-    // Only multibit devices need adaptation.
-    if (popcount(typeMask) > 1) {
-        const auto &adapter = adapters.find(type);
-        if (adapter != adapters.end()) {
-            ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
-                  adapter->second);
-            return adapter->second;
-        }
-        ALOGE("%s: failed to find map for multibit device %d", __func__, type);
-        return 0;
+    const auto &adapter = adapters.find(type);
+    if (adapter != adapters.end()) {
+        ALOGV("%s: multibit device %d converted to criterion %" PRIu64, __func__, type,
+              adapter->second);
+        return adapter->second;
     }
-    return typeMask;
+    ALOGE("%s: failed to find map for multibit device %d", __func__, type);
+    return 0;
 }
 
 uint64_t ParameterManagerWrapper::convertDeviceTypesToCriterionValue(
@@ -382,5 +359,88 @@
     return deviceTypes;
 }
 
+void ParameterManagerWrapper::createDomain(const std::string &domain)
+{
+    std::string error;
+    bool ret = mPfwConnector->createDomain(domain, error);
+    if (!ret) {
+        ALOGD("%s: failed to create domain %s (error=%s)", __func__, domain.c_str(),
+        error.c_str());
+    }
+}
+
+void ParameterManagerWrapper::addConfigurableElementToDomain(const std::string &domain,
+        const std::string &elementPath)
+{
+    std::string error;
+    bool ret = mPfwConnector->addConfigurableElementToDomain(domain, elementPath, error);
+    ALOGE_IF(!ret, "%s: failed to add parameter %s for domain %s (error=%s)",
+              __func__, elementPath.c_str(), domain.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::createConfiguration(const std::string &domain,
+        const std::string &configurationName)
+{
+    std::string error;
+    bool ret = mPfwConnector->createConfiguration(domain, configurationName, error);
+    ALOGE_IF(!ret, "%s: failed to create configuration %s for domain %s (error=%s)",
+              __func__, configurationName.c_str(), domain.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::setApplicationRule(
+        const std::string &domain, const std::string &configurationName, const std::string &rule)
+{
+    std::string error;
+    bool ret = mPfwConnector->setApplicationRule(domain, configurationName, rule, error);
+    ALOGE_IF(!ret, "%s: failed to set rule %s for domain %s and configuration %s (error=%s)",
+              __func__, rule.c_str(), domain.c_str(), configurationName.c_str(), error.c_str());
+}
+
+void ParameterManagerWrapper::accessConfigurationValue(const std::string &domain,
+        const std::string &configurationName, const std::string &elementPath,
+        std::string &value)
+{
+    std::string error;
+    bool ret = mPfwConnector->accessConfigurationValue(domain, configurationName, elementPath,
+            value, /*set=*/ true, error);
+    ALOGE_IF(!ret, "%s: failed to set value %s for parameter %s on domain %s and configuration %s "
+          "(error=%s)", __func__, value.c_str(), elementPath.c_str(),  domain.c_str(),
+          configurationName.c_str(), error.c_str());
+}
+
+status_t ParameterManagerWrapper::setConfiguration(
+        const android::capEngineConfig::ParsingResult& capSettings)
+{
+    if (!isStarted()) {
+        return NO_INIT;
+    }
+    std::string error;
+    if (!mPfwConnector->setTuningMode(/* bOn= */ true, error)) {
+        ALOGD("%s: failed to set Tuning Mode error=%s", __FUNCTION__, error.c_str());
+        return DEAD_OBJECT;
+    }
+    for (auto &domain: capSettings.parsedConfig->capConfigurableDomains) {
+        createDomain(domain.name);
+        for (const auto &configurableElementValue : domain.settings[0].configurableElementValues) {
+            addConfigurableElementToDomain(domain.name,
+                    configurableElementValue.configurableElement.path);
+        }
+        for (const auto &configuration : domain.configurations) {
+            createConfiguration(domain.name, configuration.name);
+            setApplicationRule(domain.name, configuration.name, configuration.rule);
+        }
+        for (const auto &setting : domain.settings) {
+            for (const auto &configurableElementValue : setting.configurableElementValues) {
+                std::string value = configurableElementValue.value;
+                accessConfigurationValue(domain.name, setting.configurationName,
+                        configurableElementValue.configurableElement.path, value);
+            }
+
+        }
+    }
+    mPfwConnector->setTuningMode(/* bOn= */ false, error);
+    return OK;
+}
+
 } // namespace audio_policy
 } // namespace android
diff --git a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
index fa4ae1e..0c45a60 100644
--- a/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
+++ b/services/audiopolicy/engineconfigurable/wrapper/include/ParameterManagerWrapper.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <CapEngineConfig.h>
 #include <media/AudioContainers.h>
 #include <system/audio.h>
 #include <system/audio_policy.h>
@@ -27,7 +28,7 @@
 #include <string>
 #include <vector>
 
-class CParameterMgrPlatformConnector;
+class CParameterMgrFullConnector;
 class ISelectionCriterionInterface;
 struct cnode;
 
@@ -59,6 +60,9 @@
      */
     status_t start(std::string &error);
 
+    status_t setConfiguration(const android::capEngineConfig::ParsingResult& capSettings);
+
+
     /**
      * The following API wrap policy action to criteria
      */
@@ -148,6 +152,14 @@
             uint64_t criterionValue, bool isOut) const;
 
 private:
+    void createDomain(const std::string &domain);
+    void addConfigurableElementToDomain(const std::string &domain, const std::string &elementPath);
+    void createConfiguration(const std::string &domain, const std::string &configurationName);
+    void setApplicationRule(const std::string &domain, const std::string &configurationName,
+            const std::string &rule);
+    void accessConfigurationValue(const std::string &domain, const std::string &configurationName,
+                                  const std::string &elementPath, std::string &value);
+
     /**
      * Apply the configuration of the platform on the policy parameter manager.
      * Once all the criteria have been set, the client of the platform state must call
@@ -206,7 +218,7 @@
 
     Criteria mPolicyCriteria; /**< Policy Criterion Map. */
 
-    CParameterMgrPlatformConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
+    CParameterMgrFullConnector *mPfwConnector; /**< Policy Parameter Manager connector. */
     ParameterMgrPlatformConnectorLogger *mPfwConnectorLogger; /**< Policy PFW logger. */
 
 
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index b04aff0..7e35cca 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -51,7 +51,7 @@
         { "STRATEGY_TRANSMITTED_THROUGH_SPEAKER", STRATEGY_TRANSMITTED_THROUGH_SPEAKER },
         { "STRATEGY_ACCESSIBILITY", STRATEGY_ACCESSIBILITY },
         { "STRATEGY_REROUTING", STRATEGY_REROUTING },
-        { "STRATEGY_PATCH", STRATEGY_REROUTING }, // boiler to manage stream patch volume
+        { "STRATEGY_PATCH", STRATEGY_PATCH }, // boiler to manage stream patch volume
         { "STRATEGY_CALL_ASSISTANT", STRATEGY_CALL_ASSISTANT },
     };
     return legacyStrategy;
diff --git a/services/audiopolicy/enginedefault/src/Engine.h b/services/audiopolicy/enginedefault/src/Engine.h
index a6090cf..862b5fd 100644
--- a/services/audiopolicy/enginedefault/src/Engine.h
+++ b/services/audiopolicy/enginedefault/src/Engine.h
@@ -28,20 +28,6 @@
 namespace audio_policy
 {
 
-enum legacy_strategy {
-    STRATEGY_NONE = -1,
-    STRATEGY_MEDIA,
-    STRATEGY_PHONE,
-    STRATEGY_SONIFICATION,
-    STRATEGY_SONIFICATION_RESPECTFUL,
-    STRATEGY_DTMF,
-    STRATEGY_ENFORCED_AUDIBLE,
-    STRATEGY_TRANSMITTED_THROUGH_SPEAKER,
-    STRATEGY_ACCESSIBILITY,
-    STRATEGY_REROUTING,
-    STRATEGY_CALL_ASSISTANT,
-};
-
 class Engine : public EngineBase
 {
 public:
diff --git a/services/audiopolicy/fuzzer/Android.bp b/services/audiopolicy/fuzzer/Android.bp
index 8cee613..30d4403 100644
--- a/services/audiopolicy/fuzzer/Android.bp
+++ b/services/audiopolicy/fuzzer/Android.bp
@@ -28,39 +28,18 @@
 
 cc_fuzz {
     name: "audiopolicy_fuzzer",
+    defaults: [
+        "libaudiopolicyservice_dependencies",
+    ],
     srcs: [
         "audiopolicy_fuzzer.cpp",
     ],
-    include_dirs: [
-        "frameworks/av/services/audiopolicy",
-    ],
-    shared_libs: [
-        "android.hardware.audio.common-util",
-        "capture_state_listener-aidl-cpp",
-        "framework-permission-aidl-cpp",
-        "libaudioclient",
-        "libaudiofoundation",
-        "libaudiopolicy",
-        "libaudiopolicycomponents",
-        "libaudiopolicymanagerdefault",
-        "libbase",
-        "libbinder",
-        "libcutils",
-        "libdl",
-        "libhidlbase",
-        "liblog",
-        "libmedia_helper",
-        "libmediametrics",
-        "libutils",
-        "libxml2",
-    ],
     static_libs: [
         "android.hardware.audio.common@7.0-enums",
     ],
-    header_libs: [
-        "libaudiopolicycommon",
-        "libaudiopolicyengine_interface_headers",
-        "libaudiopolicymanager_interface_headers",
+    include_dirs: [
+        "frameworks/av/services/audiopolicy", // include path outside of libaudiopolicyservice
+        "frameworks/av/services/audiopolicy/engine/interface", // for /tests/AudioPolicyTestManager.h:
     ],
     data: [":audiopolicyfuzzer_configuration_files"],
     fuzz_config: {
diff --git a/services/audiopolicy/fuzzer/aidl/Android.bp b/services/audiopolicy/fuzzer/aidl/Android.bp
index a91ecd7..680f76d 100644
--- a/services/audiopolicy/fuzzer/aidl/Android.bp
+++ b/services/audiopolicy/fuzzer/aidl/Android.bp
@@ -23,37 +23,15 @@
 cc_defaults {
     name: "audiopolicy_aidl_fuzzer_defaults",
     shared_libs: [
-        "audiopolicy-aidl-cpp",
-        "audiopolicy-types-aidl-cpp",
-        "framework-permission-aidl-cpp",
-        "libactivitymanager_aidl",
-        "libaudioclient",
         "libaudioflinger",
-        "libaudiohal",
-        "libaudiopolicy",
-        "libaudiopolicymanagerdefault",
         "libaudiopolicyservice",
-        "libaudioprocessing",
-        "libhidlbase",
-        "liblog",
-        "libmediautils",
-        "libnbaio",
-        "libnblog",
-        "libpowermanager",
-        "libvibrator",
-        "packagemanager_aidl-cpp",
-    ],
-    static_libs: [
-        "audiopermissioncontroller",
-        "libaudiomockhal",
-        "libfakeservicemanager",
         "libmediaplayerservice",
     ],
+    static_libs: [
+        "libaudiomockhal",
+        "libfakeservicemanager",
+    ],
     header_libs: [
-        "libaudioflinger_headers",
-        "libaudiohal_headers",
-        "libaudiopolicymanager_interface_headers",
-        "libbinder_headers",
         "libmedia_headers",
     ],
     fuzz_config: {
@@ -78,6 +56,8 @@
         "latest_android_hardware_audio_core_ndk_shared",
         "latest_android_hardware_audio_core_sounddose_ndk_shared",
         "latest_android_hardware_audio_effect_ndk_shared",
+        "libaudioflinger_dependencies",
+        "libaudiopolicyservice_dependencies",
         "service_fuzzer_defaults",
     ],
 }
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-0 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..4d539b7
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-1 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..8af7d2f
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-2 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..b89b77e
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-3 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..6e966e9
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-4 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-4
new file mode 100644
index 0000000..8ccf24d
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-4
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-5 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-5
new file mode 100644
index 0000000..223d1df
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-5
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-6 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-6
new file mode 100644
index 0000000..ad54b83
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-6
Binary files differ
diff --git a/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-7 b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-7
new file mode 100644
index 0000000..f4eabf4
--- /dev/null
+++ b/services/audiopolicy/fuzzer/aidl/corpus/seed-2024-08-29-7
Binary files differ
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 252dae6..2ff2907 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -768,7 +768,7 @@
         }
         muteWaitMs = setOutputDevices(__func__, mPrimaryOutput, rxDevices, true, delayMs);
     } else { // create RX path audio patch
-        connectTelephonyRxAudioSource();
+        connectTelephonyRxAudioSource(delayMs);
         // If the TX device is on the primary HW module but RX device is
         // on other HW module, SinkMetaData of telephony input should handle it
         // assuming the device uses audio HAL V5.0 and above
@@ -803,7 +803,7 @@
     return false;
 }
 
-void AudioPolicyManager::connectTelephonyRxAudioSource()
+void AudioPolicyManager::connectTelephonyRxAudioSource(uint32_t delayMs)
 {
     disconnectTelephonyAudioSource(mCallRxSourceClient);
     const struct audio_port_config source = {
@@ -813,7 +813,8 @@
     const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
 
     audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
-    status_t status = startAudioSource(&source, &aa, &portId, 0 /*uid*/, true /*internal*/);
+    status_t status = startAudioSourceInternal(&source, &aa, &portId, 0 /*uid*/,
+                                       true /*internal*/, true /*isCallRx*/, delayMs);
     ALOGE_IF(status != OK, "%s: failed to start audio source (%d)", __func__, status);
     mCallRxSourceClient = mAudioSources.valueFor(portId);
     ALOGE_IF(mCallRxSourceClient == nullptr,
@@ -850,7 +851,8 @@
     srcDevice->toAudioPortConfig(&source);
     mCallTxSourceClient = new SourceClientDescriptor(
                 callTxSourceClientPortId, mUidCached, aa, source, srcDevice, AUDIO_STREAM_PATCH,
-                mCommunnicationStrategy, toVolumeSource(aa), true);
+                mCommunnicationStrategy, toVolumeSource(aa), true,
+                false /*isCallRx*/, true /*isCallTx*/);
     mCallTxSourceClient->setPreferredDeviceId(sinkDevice->getId());
 
     audio_patch_handle_t patchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -1248,7 +1250,8 @@
 
     // FIXME: in case of RENDER policy, the output capabilities should be checked
     if ((secondaryMixes != nullptr && !secondaryMixes->empty())
-            && !audio_is_linear_pcm(config->format)) {
+            && (!audio_is_linear_pcm(config->format) ||
+                    *flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
         ALOGD("%s: rejecting request as secondary mixes only support pcm", __func__);
         return BAD_VALUE;
     }
@@ -1273,7 +1276,7 @@
             status = openDirectOutput(
                     *stream, session, config,
                     (audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT),
-                    DeviceVector(policyMixDevice), &newOutput);
+                    DeviceVector(policyMixDevice), &newOutput, *resultAttr);
             if (status == NO_ERROR) {
                 policyDesc = mOutputs.valueFor(newOutput);
                 primaryMix->setOutput(policyDesc);
@@ -1511,7 +1514,8 @@
                                               const audio_config_t *config,
                                               audio_output_flags_t flags,
                                               const DeviceVector &devices,
-                                              audio_io_handle_t *output) {
+                                              audio_io_handle_t *output,
+                                              audio_attributes_t attributes) {
 
     *output = AUDIO_IO_HANDLE_NONE;
 
@@ -1606,7 +1610,8 @@
     releaseMsdOutputPatches(devices);
 
     status_t status =
-            outputDesc->open(config, nullptr /* mixerConfig */, devices, stream, flags, output);
+            outputDesc->open(config, nullptr /* mixerConfig */, devices, stream, flags, output,
+                             attributes);
 
     // only accept an output with the requested parameters
     if (status != NO_ERROR ||
@@ -1711,7 +1716,9 @@
 
     audio_config_t directConfig = *config;
     directConfig.channel_mask = channelMask;
-    status_t status = openDirectOutput(stream, session, &directConfig, *flags, devices, &output);
+
+    status_t status = openDirectOutput(stream, session, &directConfig, *flags, devices, &output,
+                                       *attr);
     if (status != NAME_NOT_FOUND) {
         return output;
     }
@@ -2148,8 +2155,7 @@
     // matching criteria values in priority order for best matching output so far
     std::vector<uint32_t> bestMatchCriteria(8, 0);
 
-    const bool hasOrphanHaptic =
-            mEffects.hasOrphanEffectsForSessionAndType(sessionId, FX_IID_HAPTICGENERATOR);
+    const bool hasOrphanHaptic = mEffects.hasOrphansForSession(sessionId, FX_IID_HAPTICGENERATOR);
     const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
     const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(
         channelMask & AUDIO_CHANNEL_HAPTIC_ALL);
@@ -5114,7 +5120,7 @@
             new SourceClientDescriptor(
                 portId, uid, attributes, *source, srcDevice, AUDIO_STREAM_PATCH,
                 mEngine->getProductStrategyForAttributes(attributes), toVolumeSource(attributes),
-                true);
+                true, false /*isCallRx*/, false /*isCallTx*/);
     sourceDesc->setPreferredDeviceId(sinkDevice->getId());
 
     status_t status =
@@ -5446,7 +5452,7 @@
                         outputDesc->toAudioPortConfig(&srcMixPortConfig, nullptr);
                         // for volume control, we may need a valid stream
                         srcMixPortConfig.ext.mix.usecase.stream =
-                            (!sourceDesc->isInternal() || isCallTxAudioSource(sourceDesc)) ?
+                            (!sourceDesc->isInternal() || sourceDesc->isCallTx()) ?
                                     mEngine->getStreamTypeForAttributes(sourceDesc->attributes()) :
                                     AUDIO_STREAM_PATCH;
                         patchBuilder.addSource(srcMixPortConfig);
@@ -5784,7 +5790,16 @@
 status_t AudioPolicyManager::startAudioSource(const struct audio_port_config *source,
                                               const audio_attributes_t *attributes,
                                               audio_port_handle_t *portId,
-                                              uid_t uid, bool internal)
+                                              uid_t uid) {
+    return startAudioSourceInternal(source, attributes, portId, uid,
+                                    false /*internal*/, false /*isCallRx*/, 0 /*delayMs*/);
+}
+
+status_t AudioPolicyManager::startAudioSourceInternal(const struct audio_port_config *source,
+                                              const audio_attributes_t *attributes,
+                                              audio_port_handle_t *portId,
+                                              uid_t uid, bool internal, bool isCallRx,
+                                              uint32_t delayMs)
 {
     ALOGV("%s", __FUNCTION__);
     *portId = AUDIO_PORT_HANDLE_NONE;
@@ -5817,16 +5832,17 @@
         new SourceClientDescriptor(*portId, uid, *attributes, *source, srcDevice,
                                    mEngine->getStreamTypeForAttributes(*attributes),
                                    mEngine->getProductStrategyForAttributes(*attributes),
-                                   toVolumeSource(*attributes), internal);
+                                   toVolumeSource(*attributes), internal, isCallRx, false);
 
-    status_t status = connectAudioSource(sourceDesc);
+    status_t status = connectAudioSource(sourceDesc, delayMs);
     if (status == NO_ERROR) {
         mAudioSources.add(*portId, sourceDesc);
     }
     return status;
 }
 
-status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>& sourceDesc)
+status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>& sourceDesc,
+                                                uint32_t delayMs)
 {
     ALOGV("%s handle %d", __FUNCTION__, sourceDesc->portId());
 
@@ -5852,7 +5868,7 @@
     audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
 
     return connectAudioSourceToSink(
-                sourceDesc, sinkDevice, patchBuilder.patch(), handle, mUidCached, 0 /*delayMs*/);
+                sourceDesc, sinkDevice, patchBuilder.patch(), handle, mUidCached, delayMs);
 }
 
 status_t AudioPolicyManager::stopAudioSource(audio_port_handle_t portId)
@@ -6289,7 +6305,7 @@
         // means haptic use cases (either the client channelmask includes haptic bits, or created a
         // HapticGenerator effect for this session) are not supported.
         return clientHapticChannel == 0 &&
-               !mEffects.hasOrphanEffectsForSessionAndType(sessionId, FX_IID_HAPTICGENERATOR);
+               !mEffects.hasOrphansForSession(sessionId, FX_IID_HAPTICGENERATOR);
     }
 }
 
@@ -6592,10 +6608,11 @@
             sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
                                                                                  mpClientInterface);
             audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+            audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
             status_t status = outputDesc->open(nullptr /* halConfig */, nullptr /* mixerConfig */,
                                                DeviceVector(supportedDevice),
                                                AUDIO_STREAM_DEFAULT,
-                                               AUDIO_OUTPUT_FLAG_NONE, &output);
+                                               AUDIO_OUTPUT_FLAG_NONE, &output, attributes);
             if (status != NO_ERROR) {
                 ALOGW("Cannot open output stream for devices %s on hw module %s",
                       supportedDevice->toString().c_str(), hwModule->getName());
@@ -6663,7 +6680,7 @@
             status_t status = inputDesc->open(nullptr,
                                               availProfileDevices.itemAt(0),
                                               AUDIO_SOURCE_MIC,
-                                              AUDIO_INPUT_FLAG_NONE,
+                                              (audio_input_flags_t) inProfile->getFlags(),
                                               &input);
             if (status != NO_ERROR) {
                 ALOGW("%s: Cannot open input stream for device %s for profile %s on hw module %s",
@@ -6978,7 +6995,8 @@
             desc = new AudioInputDescriptor(profile, mpClientInterface);
             audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
             ALOGV("%s opening input for profile %s", __func__, profile->getTagName().c_str());
-            status = desc->open(nullptr, device, AUDIO_SOURCE_MIC, AUDIO_INPUT_FLAG_NONE, &input);
+            status = desc->open(nullptr, device, AUDIO_SOURCE_MIC,
+                                (audio_input_flags_t) profile->getFlags(), &input);
 
             if (status == NO_ERROR) {
                 const String8& address = String8(device->address().c_str());
@@ -7225,8 +7243,8 @@
         sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
         if (sourceDesc != nullptr && followsSameRouting(attr, sourceDesc->attributes())
                 && sourceDesc->getPatchHandle() == AUDIO_PATCH_HANDLE_NONE
-                && !isCallRxAudioSource(sourceDesc) && !sourceDesc->isInternal()) {
-            connectAudioSource(sourceDesc);
+                && !sourceDesc->isCallRx() && !sourceDesc->isInternal()) {
+            connectAudioSource(sourceDesc, 0 /*delayMs*/);
         }
     }
 }
@@ -7257,28 +7275,35 @@
     std::vector<sp<SwAudioOutputDescriptor>> invalidatedOutputs;
     // take into account dynamic audio policies related changes: if a client is now associated
     // to a different policy mix than at creation time, invalidate corresponding stream
+    // invalidate clients on outputs that do not support all the newly selected devices for the
+    // strategy
     for (size_t i = 0; i < mPreviousOutputs.size(); i++) {
         const sp<SwAudioOutputDescriptor>& desc = mPreviousOutputs.valueAt(i);
-        if (desc->isDuplicated()) {
+        if (desc->isDuplicated() || desc->getClientCount() == 0) {
             continue;
         }
+
         for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) {
             if (mEngine->getProductStrategyForAttributes(client->attributes()) != psId) {
                 continue;
             }
+            if (!desc->supportsAllDevices(newDevices)) {
+                invalidatedOutputs.push_back(desc);
+                break;
+            }
             sp<AudioPolicyMix> primaryMix;
             status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->config(),
                     client->uid(), client->session(), client->flags(), mAvailableOutputDevices,
                     nullptr /* requestedDevice */, primaryMix, nullptr /* secondaryMixes */,
                     unneededUsePrimaryOutputFromPolicyMixes);
-            if (status != OK) {
-                continue;
-            }
-            if (client->getPrimaryMix() != primaryMix || client->hasLostPrimaryMix()) {
-                if (desc->isStrategyActive(psId) && maxLatency < desc->latency()) {
-                    maxLatency = desc->latency();
+            if (status == OK) {
+                if (client->getPrimaryMix() != primaryMix || client->hasLostPrimaryMix()) {
+                    if (desc->isStrategyActive(psId) && maxLatency < desc->latency()) {
+                        maxLatency = desc->latency();
+                    }
+                    invalidatedOutputs.push_back(desc);
+                    break;
                 }
-                invalidatedOutputs.push_back(desc);
             }
         }
     }
@@ -7332,8 +7357,8 @@
                 }
             }
             sp<SourceClientDescriptor> source = getSourceForAttributesOnOutput(srcOut, attr);
-            if (source != nullptr && !isCallRxAudioSource(source) && !source->isInternal()) {
-                connectAudioSource(source);
+            if (source != nullptr && !source->isCallRx() && !source->isInternal()) {
+                connectAudioSource(source, 0 /*delayMs*/);
             }
         }
 
@@ -7396,7 +7421,8 @@
                     client->getSecondaryOutputs().begin(),
                     client->getSecondaryOutputs().end(),
                     secondaryDescs.begin(), secondaryDescs.end())) {
-                if (!audio_is_linear_pcm(client->config().format)) {
+                if (client->flags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
+                        || !audio_is_linear_pcm(client->config().format)) {
                     // If the format is not PCM, the tracks should be invalidated to get correct
                     // behavior when the secondary output is changed.
                     clientsToInvalidate.push_back(client->portId());
@@ -8274,6 +8300,9 @@
                                                int delayMs,
                                                bool force)
 {
+    // APM is single threaded, and single instance.
+    static std::set<IVolumeCurves*> invalidCurvesReported;
+
     // do not change actual attributes volume if the attributes is muted
     if (outputDesc->isMuted(volumeSource)) {
         ALOGVV("%s: volume source %d muted count %d active=%d", __func__, volumeSource,
@@ -8298,7 +8327,12 @@
     }
 
     if (curves.getVolumeIndexMin() < 0 || curves.getVolumeIndexMax() < 0) {
-        ALOGE("invalid volume index range");
+        if (!invalidCurvesReported.count(&curves)) {
+            invalidCurvesReported.insert(&curves);
+            String8 dump;
+            curves.dump(&dump);
+            ALOGE("invalid volume index range in the curve:\n%s", dump.c_str());
+        }
         return BAD_VALUE;
     }
 
@@ -8505,7 +8539,7 @@
         sp<SourceClientDescriptor> sourceDesc = mAudioSources.valueAt(i);
         if (sourceDesc->isConnected() && (sourceDesc->srcDevice()->equals(deviceDesc) ||
                                           sourceDesc->sinkDevice()->equals(deviceDesc))
-                && !isCallRxAudioSource(sourceDesc)) {
+                && !sourceDesc->isCallRx()) {
             disconnectAudioSource(sourceDesc);
         }
     }
@@ -8791,8 +8825,9 @@
     }
     sp<SwAudioOutputDescriptor> desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
     audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
     status_t status = desc->open(halConfig, mixerConfig, devices,
-            AUDIO_STREAM_DEFAULT, flags, &output);
+            AUDIO_STREAM_DEFAULT, flags, &output, attributes);
     if (status != NO_ERROR) {
         ALOGE("%s failed to open output %d", __func__, status);
         return nullptr;
@@ -8830,7 +8865,8 @@
         config.offload_info.channel_mask = config.channel_mask;
         config.offload_info.format = config.format;
 
-        status = desc->open(&config, mixerConfig, devices, AUDIO_STREAM_DEFAULT, flags, &output);
+        status = desc->open(&config, mixerConfig, devices, AUDIO_STREAM_DEFAULT, flags, &output,
+                            attributes);
         if (status != NO_ERROR) {
             return nullptr;
         }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 011e867..953fd2a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -345,8 +345,7 @@
         virtual status_t startAudioSource(const struct audio_port_config *source,
                                           const audio_attributes_t *attributes,
                                           audio_port_handle_t *portId,
-                                          uid_t uid,
-                                          bool internal = false);
+                                          uid_t uid);
         virtual status_t stopAudioSource(audio_port_handle_t portId);
 
         virtual status_t setMasterMono(bool mono);
@@ -705,15 +704,7 @@
         void updateCallAndOutputRouting(bool forceVolumeReeval = true, uint32_t delayMs = 0,
                 bool skipDelays = false);
 
-        bool isCallRxAudioSource(const sp<SourceClientDescriptor> &source) {
-            return mCallRxSourceClient != nullptr && source == mCallRxSourceClient;
-        }
-
-        bool isCallTxAudioSource(const sp<SourceClientDescriptor> &source) {
-            return mCallTxSourceClient != nullptr && source == mCallTxSourceClient;
-        }
-
-        void connectTelephonyRxAudioSource();
+        void connectTelephonyRxAudioSource(uint32_t delayMs);
 
         void disconnectTelephonyAudioSource(sp<SourceClientDescriptor> &clientDesc);
 
@@ -938,7 +929,8 @@
 
         status_t hasPrimaryOutput() const { return mPrimaryOutput != 0; }
 
-        status_t connectAudioSource(const sp<SourceClientDescriptor>& sourceDesc);
+        status_t connectAudioSource(const sp<SourceClientDescriptor>& sourceDesc,
+                                    uint32_t delayMs);
         status_t disconnectAudioSource(const sp<SourceClientDescriptor>& sourceDesc);
 
         status_t connectAudioSourceToSink(const sp<SourceClientDescriptor>& sourceDesc,
@@ -976,6 +968,13 @@
         void checkLeBroadcastRoutes(bool wasUnicastActive,
                 sp<SwAudioOutputDescriptor> ignoredOutput, uint32_t delayMs);
 
+        status_t startAudioSourceInternal(const struct audio_port_config *source,
+                                          const audio_attributes_t *attributes,
+                                          audio_port_handle_t *portId,
+                                          uid_t uid,
+                                          bool internal,
+                                          bool isCallRx,
+                                          uint32_t delayMs);
         const uid_t mUidCached;                         // AID_AUDIOSERVER
         sp<const AudioPolicyConfig> mConfig;
         EngineInstance mEngine;                         // Audio Policy Engine instance
@@ -1153,7 +1152,8 @@
                 const audio_config_t *config,
                 audio_output_flags_t flags,
                 const DeviceVector &devices,
-                audio_io_handle_t *output);
+                audio_io_handle_t *output,
+                audio_attributes_t attributes);
 
         /**
          * @brief Queries if some kind of spatialization will be performed if the audio playback
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index 84458f9..e157808 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -11,12 +11,16 @@
 cc_defaults {
     name: "libaudiopolicyservice_dependencies",
 
-    header_libs: ["audiopolicyservicelocal_headers"],
+    include_dirs: [
+        "frameworks/av/services/audiopolicy", // include path outside of libaudiopolicyservice
+    ],
 
     shared_libs: [
         "android.media.audiopolicy-aconfig-cc",
+        "audio-permission-aidl-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
+        "audiopermissioncontroller",
         "audiopolicy-aidl-cpp",
         "audiopolicy-types-aidl-cpp",
         "capture_state_listener-aidl-cpp",
@@ -35,6 +39,7 @@
         "libaudioutils",
         "libbinder",
         "libcutils",
+        "libeffectsconfig",
         "libhardware_legacy",
         "libheadtracking",
         "libheadtracking-binding",
@@ -52,13 +57,6 @@
         "packagemanager_aidl-cpp",
         "spatializer-aidl-cpp",
     ],
-
-    static_libs: [
-        "audio-permission-aidl-cpp",
-        "audiopermissioncontroller",
-        "libaudiopolicycomponents",
-        "libeffectsconfig",
-    ],
 }
 
 cc_library {
@@ -84,10 +82,6 @@
         "frameworks/av/services/audioflinger",
     ],
 
-    static_libs: [
-        "framework-permission-aidl-cpp", // TODO remove when unnnecessary
-    ],
-
     header_libs: [
         "audiopolicyservicelocal_headers",
         "libaudiohal_headers",
@@ -97,21 +91,14 @@
         "libaudioutils_headers",
     ],
 
+    export_include_dirs: ["."],
+
     cflags: [
         "-Wall",
         "-Werror",
         "-Wthread-safety",
         "-fvisibility=hidden",
     ],
-
-    export_shared_lib_headers: [
-        "framework-permission-aidl-cpp",
-        "libactivitymanager_aidl",
-        "libaudiousecasevalidation",
-        "libheadtracking",
-        "libheadtracking-binding",
-        "libsensorprivacy",
-    ],
 }
 
 cc_library_headers {
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index f70dc52..22fc151 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -56,7 +56,8 @@
                                                            audio_config_base_t *mixerConfig,
                                                            const sp<DeviceDescriptorBase>& device,
                                                            uint32_t *latencyMs,
-                                                           audio_output_flags_t flags)
+                                                           audio_output_flags_t flags,
+                                                           audio_attributes_t attributes)
 {
     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
     if (af == 0) {
@@ -74,6 +75,8 @@
             legacy2aidl_audio_config_base_t_AudioConfigBase(*mixerConfig, false /*isInput*/));
     request.device = VALUE_OR_RETURN_STATUS(legacy2aidl_DeviceDescriptorBase(device));
     request.flags = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
+    request.attributes = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_attributes_t_AudioAttributes(attributes));
 
     status_t status = af->openOutput(request, &response);
     if (status == OK) {
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 768cd07..b2f0c22 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -60,6 +60,8 @@
 using media::audio::common::AudioFormatDescription;
 using media::audio::common::AudioMode;
 using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioPolicyForceUse;
+using media::audio::common::AudioPolicyForcedConfig;
 using media::audio::common::AudioSource;
 using media::audio::common::AudioStreamType;
 using media::audio::common::AudioUsage;
@@ -253,8 +255,8 @@
     return Status::ok();
 }
 
-Status AudioPolicyService::setForceUse(media::AudioPolicyForceUse usageAidl,
-                                       media::AudioPolicyForcedConfig configAidl)
+Status AudioPolicyService::setForceUse(AudioPolicyForceUse usageAidl,
+                                       AudioPolicyForcedConfig configAidl)
 {
     audio_policy_force_use_t usage = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(usageAidl));
@@ -283,8 +285,8 @@
     return Status::ok();
 }
 
-Status AudioPolicyService::getForceUse(media::AudioPolicyForceUse usageAidl,
-                                       media::AudioPolicyForcedConfig* _aidl_return) {
+Status AudioPolicyService::getForceUse(AudioPolicyForceUse usageAidl,
+                                       AudioPolicyForcedConfig* _aidl_return) {
     audio_policy_force_use_t usage = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPolicyForceUse_audio_policy_force_use_t(usageAidl));
 
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index cc67481..d529130 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -193,9 +193,7 @@
     media::AudioPolicyConfig apmConfig;
     if (status_t status = clientInterface->getAudioPolicyConfig(&apmConfig); status == OK) {
         auto config = AudioPolicyConfig::loadFromApmAidlConfigWithFallback(apmConfig);
-        LOG_ALWAYS_FATAL_IF(config->getEngineLibraryNameSuffix() !=
-                AudioPolicyConfig::kDefaultEngineLibraryNameSuffix,
-                "Only default engine is currently supported with the AIDL HAL");
+        ALOGD("%s loading APM engine %s", __func__, config->getEngineLibraryNameSuffix().c_str());
         apm = new AudioPolicyManager(config,
                 loadApmEngineLibraryAndCreateEngine(
                         config->getEngineLibraryNameSuffix(), apmConfig.engineConfig),
@@ -1415,8 +1413,8 @@
         } else {
             getIAudioPolicyServiceStatistics().event(code, elapsedMs);
         }
-    }, mediautils::TimeCheck::kDefaultTimeoutDuration,
-    mediautils::TimeCheck::kDefaultSecondChanceDuration,
+    }, mediautils::TimeCheck::getDefaultTimeoutDuration(),
+    mediautils::TimeCheck::getDefaultSecondChanceDuration(),
     true /* crashOnTimeout */);
 
     switch (code) {
@@ -1803,6 +1801,7 @@
                   ++numTimesBecameEmpty;
                 }
                 mLastCommand = command;
+                status_t createAudioPatchStatus;
 
                 switch (command->mCommand) {
                 case SET_VOLUME: {
@@ -1860,10 +1859,11 @@
                     ALOGV("AudioCommandThread() processing create audio patch");
                     sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
                     if (af == 0) {
-                        command->mStatus = PERMISSION_DENIED;
+                        createAudioPatchStatus = PERMISSION_DENIED;
                     } else {
                         ul.unlock();
-                        command->mStatus = af->createAudioPatch(&data->mPatch, &data->mHandle);
+                        createAudioPatchStatus = af->createAudioPatch(&data->mPatch,
+                                                                      &data->mHandle);
                         ul.lock();
                     }
                     } break;
@@ -2032,8 +2032,28 @@
                 {
                     audio_utils::lock_guard _l(command->mMutex);
                     if (command->mWaitStatus) {
+                        if (command->mCommand == CREATE_AUDIO_PATCH) {
+                            command->mStatus = createAudioPatchStatus;
+                        }
                         command->mWaitStatus = false;
                         command->mCond.notify_one();
+                    } else if (command->mCommand == CREATE_AUDIO_PATCH &&
+                               command->mStatus == TIMED_OUT &&
+                               createAudioPatchStatus == NO_ERROR) {
+                        // Because of special handling in insertCommand_l() the CREATE_AUDIO_PATCH
+                        // command wait status can be only false in case timeout (see TIMED_OUT)
+                        // happened.
+                        CreateAudioPatchData *createData =
+                                (CreateAudioPatchData *)command->mParam.get();
+                        ALOGW("AudioCommandThread() no caller awaiting for handle(%d) after \
+                                processing create audio patch, going to release it",
+                                createData->mHandle);
+                        sp<AudioCommand> releaseCommand = new AudioCommand();
+                        releaseCommand->mCommand = RELEASE_AUDIO_PATCH;
+                        ReleaseAudioPatchData *releaseData = new ReleaseAudioPatchData();
+                        releaseData->mHandle = createData->mHandle;
+                        releaseCommand->mParam = releaseData;
+                        insertCommand_l(releaseCommand, 0);
                     }
                 }
                 waitTime = -1;
@@ -2551,7 +2571,8 @@
 
     // Disable wait for status if delay is not 0.
     // Except for create audio patch command because the returned patch handle
-    // is needed by audio policy manager
+    // is needed by audio policy manager. Audio patch created after timeout
+    // (see TIMED_OUT) will be released from threadLoop().
     if (delayMs != 0 && command->mCommand != CREATE_AUDIO_PATCH) {
         command->mWaitStatus = false;
     }
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 699cacf..5d9813f 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -105,10 +105,10 @@
             const std::string& deviceName,
             const AudioFormatDescription& encodedFormat) override;
     binder::Status setPhoneState(AudioMode state, int32_t uid) override;
-    binder::Status setForceUse(media::AudioPolicyForceUse usage,
-                               media::AudioPolicyForcedConfig config) override;
-    binder::Status getForceUse(media::AudioPolicyForceUse usage,
-                               media::AudioPolicyForcedConfig* _aidl_return) override;
+    binder::Status setForceUse(android::media::audio::common::AudioPolicyForceUse usage,
+            android::media::audio::common::AudioPolicyForcedConfig config) override;
+    binder::Status getForceUse(android::media::audio::common::AudioPolicyForceUse usage,
+            android::media::audio::common::AudioPolicyForcedConfig* _aidl_return) override;
     binder::Status getOutput(AudioStreamType stream, int32_t* _aidl_return) override;
     binder::Status getOutputForAttr(const media::audio::common::AudioAttributes& attr,
                                     int32_t session,
@@ -790,7 +790,8 @@
                                     audio_config_base_t *mixerConfig,
                                     const sp<DeviceDescriptorBase>& device,
                                     uint32_t *latencyMs,
-                                    audio_output_flags_t flags);
+                                    audio_output_flags_t flags,
+                                    audio_attributes_t attributes);
         // creates a special output that is duplicated to the two outputs passed as arguments. The duplication is performed by
         // a special mixer thread in the AudioFlinger.
         virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2);
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index dc61115..c600fb6 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -12,6 +12,7 @@
     name: "audiopolicy_tests",
 
     defaults: [
+        "aconfig_lib_cc_shared_link.defaults",
         "latest_android_media_audio_common_types_cpp_static",
     ],
 
@@ -106,7 +107,7 @@
         "-Werror",
     ],
 
-    test_suites: ["device-tests"],
+    test_suites: ["general-tests"],
 
 }
 
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index 46e6a0b..ca7ad40 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -42,7 +42,8 @@
                         audio_config_base_t *mixerConfig,
                         const sp<DeviceDescriptorBase>& /*device*/,
                         uint32_t * /*latencyMs*/,
-                        audio_output_flags_t flags) override {
+                        audio_output_flags_t flags,
+                        audio_attributes_t /*attributes*/) override {
         if (module >= mNextModuleHandle) {
             ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
                   __func__, module, mNextModuleHandle);
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index c15adcb..0299160 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -37,7 +37,8 @@
                         audio_config_base_t* /*mixerConfig*/,
                         const sp<DeviceDescriptorBase>& /*device*/,
                         uint32_t* /*latencyMs*/,
-                        audio_output_flags_t /*flags*/) override { return NO_INIT; }
+                        audio_output_flags_t /*flags*/,
+                        audio_attributes_t /*attributes*/) override { return NO_INIT; }
     audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
                                           audio_io_handle_t /*output2*/) override {
         return AUDIO_IO_HANDLE_NONE;
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 34ceeab..bf45bb2 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -24,9 +24,11 @@
     explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
             : AudioPolicyTestManager(AudioPolicyConfig::createDefault(), clientInterface) {}
     AudioPolicyTestManager(const sp<const AudioPolicyConfig>& config,
-            AudioPolicyClientInterface *clientInterface)
+            AudioPolicyClientInterface *clientInterface,
+            std::string engineConfig = "")
             : AudioPolicyManager(config,
-                    loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix()),
+                    loadApmEngineLibraryAndCreateEngine(config->getEngineLibraryNameSuffix(),
+                                                        engineConfig),
                     clientInterface) {}
     using AudioPolicyManager::getConfig;
     using AudioPolicyManager::initialize;
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 75d17d2..08855c9 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -227,12 +227,17 @@
     sp<AudioPolicyConfig> mConfig;
     std::unique_ptr<AudioPolicyManagerTestClient> mClient;
     std::unique_ptr<AudioPolicyTestManager> mManager;
+
+    static const std::string sTestEngineConfig;
 };
 
+const std::string AudioPolicyManagerTest::sTestEngineConfig =
+        base::GetExecutableDirectory() + "/engine/test_audio_policy_engine_configuration.xml";
+
 void AudioPolicyManagerTest::SetUp() {
     mClient.reset(getClient());
     ASSERT_NO_FATAL_FAILURE(SetUpManagerConfig());  // Subclasses may want to customize the config.
-    mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get()));
+    mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get(), sTestEngineConfig));
     ASSERT_EQ(NO_ERROR, mManager->initialize());
     ASSERT_EQ(NO_ERROR, mManager->initCheck());
 }
@@ -2512,10 +2517,12 @@
                         audio_config_base_t * mixerConfig,
                         const sp<DeviceDescriptorBase>& device,
                         uint32_t * latencyMs,
-                        audio_output_flags_t flags) override {
+                        audio_output_flags_t flags,
+                        audio_attributes_t attributes) override {
         return mSimulateFailure ? BAD_VALUE :
                 AudioPolicyManagerTestClient::openOutput(
-                        module, output, halConfig, mixerConfig, device, latencyMs, flags);
+                        module, output, halConfig, mixerConfig, device, latencyMs, flags,
+                        attributes);
     }
 
     status_t openInput(audio_module_handle_t module,
diff --git a/services/audiopolicy/tests/resources/Android.bp b/services/audiopolicy/tests/resources/Android.bp
index 42a57d3..8e7a697 100644
--- a/services/audiopolicy/tests/resources/Android.bp
+++ b/services/audiopolicy/tests/resources/Android.bp
@@ -11,6 +11,10 @@
 filegroup {
     name: "audiopolicytest_configuration_files",
     srcs: [
+        "engine/test_audio_policy_engine_configuration.xml",
+        "engine/test_audio_policy_engine_default_stream_volumes.xml",
+        "engine/test_audio_policy_engine_product_strategies.xml",
+        "engine/test_audio_policy_engine_stream_volumes.xml",
         "test_audio_policy_configuration.xml",
         "test_audio_policy_configuration_bluetooth.xml",
         "test_audio_policy_primary_only_configuration.xml",
diff --git a/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_configuration.xml b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_configuration.xml
new file mode 100644
index 0000000..dc2e7af
--- /dev/null
+++ b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_configuration.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+     -->
+
+<configuration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+
+    <xi:include href="test_audio_policy_engine_product_strategies.xml"/>
+    <xi:include href="test_audio_policy_engine_stream_volumes.xml"/>
+    <xi:include href="test_audio_policy_engine_default_stream_volumes.xml"/>
+
+</configuration>
+
diff --git a/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_default_stream_volumes.xml b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_default_stream_volumes.xml
new file mode 100644
index 0000000..d184cb5
--- /dev/null
+++ b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_default_stream_volumes.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- Default Volume Tables included by Audio Policy Configuration file -->
+<!-- Full Default Volume table for all device category -->
+<volumes>
+    <reference name="FULL_SCALE_VOLUME_CURVE">
+    <!-- Full Scale reference Volume Curve -->
+        <point>0,0</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="SILENT_VOLUME_CURVE">
+        <point>0,-9600</point>
+        <point>100,-9600</point>
+    </reference>
+    <reference name="DEFAULT_SYSTEM_VOLUME_CURVE">
+    <!-- Default System reference Volume Curve -->
+        <point>1,-2400</point>
+        <point>33,-1800</point>
+        <point>66,-1200</point>
+        <point>100,-600</point>
+    </reference>
+    <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+    <!-- Default Media reference Volume Curve -->
+        <point>1,-5800</point>
+        <point>20,-4000</point>
+        <point>60,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE">
+    <!--Default Volume Curve -->
+        <point>1,-4950</point>
+        <point>33,-3350</point>
+        <point>66,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE">
+    <!-- Default is Speaker Media Volume Curve -->
+        <point>1,-5800</point>
+        <point>20,-4000</point>
+        <point>60,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_DEVICE_CATEGORY_SPEAKER_SYSTEM_VOLUME_CURVE">
+    <!-- Default is Speaker System Volume Curve -->
+        <point>1,-4680</point>
+        <point>42,-2070</point>
+        <point>85,-540</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_DEVICE_CATEGORY_EARPIECE_VOLUME_CURVE">
+    <!--Default Volume Curve -->
+        <point>1,-4950</point>
+        <point>33,-3350</point>
+        <point>66,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE">
+    <!-- Default is Ext Media System Volume Curve -->
+        <point>1,-5800</point>
+        <point>20,-4000</point>
+        <point>60,-2100</point>
+        <point>100,-1000</point>
+    </reference>
+    <reference name="DEFAULT_HEARING_AID_VOLUME_CURVE">
+    <!-- Default Hearing Aid Volume Curve -->
+        <point>1,-12700</point>
+        <point>20,-8000</point>
+        <point>60,-4000</point>
+        <point>100,0</point>
+    </reference>
+    <!-- **************************************************************** -->
+    <!-- Non-mutable default volume curves:                               -->
+    <!--     * first point is always for index 0                          -->
+    <!--     * attenuation is small enough that stream can still be heard -->
+    <reference name="DEFAULT_NON_MUTABLE_VOLUME_CURVE">
+    <!-- Default non-mutable reference Volume Curve -->
+    <!--        based on DEFAULT_MEDIA_VOLUME_CURVE -->
+        <point>0,-5800</point>
+        <point>20,-4000</point>
+        <point>60,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE">
+    <!--Default non-mutable Volume Curve for headset -->
+    <!--    based on DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE -->
+        <point>0,-4950</point>
+        <point>33,-3350</point>
+        <point>66,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_NON_MUTABLE_SPEAKER_VOLUME_CURVE">
+    <!-- Default non-mutable Speaker Volume Curve -->
+    <!--    based on DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE -->
+        <point>0,-5800</point>
+        <point>20,-4000</point>
+        <point>60,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_NON_MUTABLE_EARPIECE_VOLUME_CURVE">
+    <!--Default non-mutable Volume Curve -->
+    <!--    based on DEFAULT_DEVICE_CATEGORY_EARPIECE_VOLUME_CURVE -->
+        <point>0,-4950</point>
+        <point>33,-3350</point>
+        <point>66,-1700</point>
+        <point>100,0</point>
+    </reference>
+    <reference name="DEFAULT_NON_MUTABLE_EXT_VOLUME_CURVE">
+    <!-- Default non-mutable Ext Media System Volume Curve -->
+    <!--     based on DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE -->
+        <point>0,-5800</point>
+        <point>20,-4000</point>
+        <point>60,-2100</point>
+        <point>100,-1000</point>
+    </reference>
+    <reference name="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE">
+    <!-- Default non-mutable Hearing Aid Volume Curve -->
+    <!--     based on DEFAULT_HEARING_AID_VOLUME_CURVE -->
+        <point>0,-12700</point>
+        <point>20,-8000</point>
+        <point>60,-4000</point>
+        <point>100,0</point>
+    </reference>
+</volumes>
diff --git a/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_product_strategies.xml b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_product_strategies.xml
new file mode 100644
index 0000000..58e7152
--- /dev/null
+++ b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_product_strategies.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+     -->
+
+<ProductStrategies>
+
+    <!-- "hidden strategies" like TTS, enforced audible:
+            Shall we expose them here or keep it hard coded -->
+
+    <!-- Used to identify the volume of audio streams for enforced system sounds in certain
+         countries (e.g. camera in Japan)
+         This strategy will only have higher priority than phone if force for system is set to
+         enforced. -->
+
+    <ProductStrategy name="STRATEGY_PHONE">
+        <AttributesGroup streamType="AUDIO_STREAM_VOICE_CALL" volumeGroup="voice_call">
+            <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION"/> </Attributes>
+        </AttributesGroup>
+        <AttributesGroup streamType="AUDIO_STREAM_BLUETOOTH_SCO" volumeGroup="bluetooth_sco">
+            <Attributes> <Flags value="AUDIO_FLAG_SCO"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <ProductStrategy name="STRATEGY_SONIFICATION">
+        <AttributesGroup streamType="AUDIO_STREAM_RING" volumeGroup="ring">
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE"/> </Attributes>
+        </AttributesGroup>
+        <AttributesGroup streamType="AUDIO_STREAM_ALARM" volumeGroup="alarm">
+            <Attributes> <Usage value="AUDIO_USAGE_ALARM"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <ProductStrategy name="STRATEGY_ENFORCED_AUDIBLE">
+        <AttributesGroup streamType="AUDIO_STREAM_ENFORCED_AUDIBLE" volumeGroup="enforced_audible">
+            <Attributes> <Flags value="AUDIO_FLAG_AUDIBILITY_ENFORCED"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <ProductStrategy name="STRATEGY_ACCESSIBILITY">
+        <AttributesGroup streamType="AUDIO_STREAM_ACCESSIBILITY" volumeGroup="accessibility">
+            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <ProductStrategy name="STRATEGY_SONIFICATION_RESPECTFUL">
+        <AttributesGroup streamType="AUDIO_STREAM_NOTIFICATION" volumeGroup="notification">
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_NOTIFICATION_EVENT"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <ProductStrategy name="STRATEGY_MEDIA">
+        <AttributesGroup streamType="AUDIO_STREAM_ASSISTANT" volumeGroup="assistant">
+            <Attributes>
+                <ContentType value="AUDIO_CONTENT_TYPE_SPEECH"/>
+                <Usage value="AUDIO_USAGE_ASSISTANT"/>
+            </Attributes>
+        </AttributesGroup>
+         <AttributesGroup streamType="AUDIO_STREAM_MUSIC" volumeGroup="music">
+            <Attributes> <Usage value="AUDIO_USAGE_MEDIA"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_GAME"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANT"/> </Attributes>
+            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE"/> </Attributes>
+            <Attributes></Attributes>
+        </AttributesGroup>
+        <AttributesGroup streamType="AUDIO_STREAM_SYSTEM" volumeGroup="system">
+            <Attributes> <Usage value="AUDIO_USAGE_ASSISTANCE_SONIFICATION"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <ProductStrategy name="STRATEGY_DTMF">
+        <AttributesGroup streamType="AUDIO_STREAM_DTMF" volumeGroup="dtmf">
+            <Attributes> <Usage value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+    <!-- Used to identify the volume of audio streams exclusively transmitted through the  speaker
+         (TTS) of the device -->
+    <ProductStrategy name="STRATEGY_TRANSMITTED_THROUGH_SPEAKER">
+        <AttributesGroup streamType="AUDIO_STREAM_TTS" volumeGroup="tts">
+            <Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
+        </AttributesGroup>
+    </ProductStrategy>
+
+</ProductStrategies>
+
diff --git a/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_stream_volumes.xml b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_stream_volumes.xml
new file mode 100644
index 0000000..af517cf
--- /dev/null
+++ b/services/audiopolicy/tests/resources/engine/test_audio_policy_engine_stream_volumes.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- Volume section defines a volume curve for a given use case and device category.
+It contains a list of points of this curve expressing the attenuation in Millibels for a given
+volume index from 0 to 100.
+<volume deviceCategory=””>
+<point>0,-9600</point>
+<point>100,0</point>
+</volume>
+-->
+
+<volumeGroups>
+    <volumeGroup>
+        <name>voice_call</name>
+        <indexMin>1</indexMin>
+        <indexMax>7</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-2400</point>
+            <point>33,-1600</point>
+            <point>66,-800</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,-2700</point>
+            <point>33,-1800</point>
+            <point>66,-900</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>system</name>
+        <indexMin>0</indexMin>
+        <indexMax>7</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>1,-3000</point>
+            <point>33,-2600</point>
+            <point>66,-2200</point>
+            <point>100,-1800</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>1,-5100</point>
+            <point>57,-2800</point>
+            <point>71,-2500</point>
+            <point>85,-2300</point>
+            <point>100,-2100</point>
+        </volume>
+        <!--volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_SYSTEM_VOLUME_CURVE"/-->
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_SYSTEM_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>ring</name>
+        <indexMin>0</indexMin>
+        <indexMax>7</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_DEVICE_CATEGORY_EARPIECE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>music</name>
+        <indexMin>0</indexMin>
+        <indexMax>25</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID"  ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>alarm</name>
+        <indexMin>1</indexMin>
+        <indexMax>7</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_NON_MUTABLE_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_NON_MUTABLE_EARPIECE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_NON_MUTABLE_EXT_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>notification</name>
+        <indexMin>0</indexMin>
+        <indexMax>7</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_SYSTEM_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_DEVICE_CATEGORY_EARPIECE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>bluetooth_sco</name>
+        <indexMin>0</indexMin>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>0,-2400</point>
+            <point>33,-1600</point>
+            <point>66,-800</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE">
+            <point>0,-4200</point>
+            <point>33,-2800</point>
+            <point>66,-1400</point>
+            <point>100,0</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>enforced_audible</name>
+        <indexMin>0</indexMin>
+        <indexMax>7</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>1,-3000</point>
+            <point>33,-2600</point>
+            <point>66,-2200</point>
+            <point>100,-1800</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>1,-3400</point>
+            <point>71,-2400</point>
+            <point>100,-2000</point>
+        </volume>
+        <!--volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_SYSTEM_VOLUME_CURVE"/-->
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_SYSTEM_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>dtmf</name>
+        <indexMin>0</indexMin>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+            <point>1,-3000</point>
+            <point>33,-2600</point>
+            <point>66,-2200</point>
+            <point>100,-1800</point>
+        </volume>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER">
+            <point>1,-4000</point>
+            <point>71,-2400</point>
+            <point>100,-1400</point>
+        </volume>
+        <!--volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_SYSTEM_VOLUME_CURVE"/-->
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_SYSTEM_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>tts</name>
+        <indexMin>0</indexMin>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="SILENT_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="SILENT_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="SILENT_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>accessibility</name>
+        <indexMin>1</indexMin>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_NON_MUTABLE_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_NON_MUTABLE_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID" ref="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+    <volumeGroup>
+        <name>assistant</name>
+        <indexMin>0</indexMin>
+        <indexMax>15</indexMax>
+        <volume deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+        <volume deviceCategory="DEVICE_CATEGORY_HEARING_AID"  ref="DEFAULT_HEARING_AID_VOLUME_CURVE"/>
+    </volumeGroup>
+
+</volumeGroups>
+
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index 38476a4..0c4bfcb 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -265,9 +265,21 @@
         "liblog",
         "libutils",
         "libxml2",
-        "camera_platform_flags_c_lib",
     ],
 
+    target: {
+        android: {
+            shared_libs: [
+                "camera_platform_flags_c_lib",
+            ],
+        },
+        host: {
+            shared_libs: [
+                "camera_platform_flags_c_lib_for_test",
+            ],
+        },
+    },
+
     include_dirs: [
         "frameworks/av/camera/include",
         "frameworks/av/camera/include/camera",
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index acc3b32..516e8f0 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -513,7 +513,7 @@
 void CameraService::onDeviceStatusChanged(const std::string& cameraId,
         CameraDeviceStatus newHalStatus) {
     ALOGI("%s: Status changed for cameraId=%s, newStatus=%d", __FUNCTION__,
-            cameraId.c_str(), newHalStatus);
+            cameraId.c_str(), eToI(newHalStatus));
 
     StatusInternal newStatus = mapToInternal(newHalStatus);
 
@@ -537,7 +537,8 @@
     StatusInternal oldStatus = state->getStatus();
 
     if (oldStatus == newStatus) {
-        ALOGE("%s: State transition to the same status %#x not allowed", __FUNCTION__, newStatus);
+        ALOGE("%s: State transition to the same status %#x not allowed", __FUNCTION__,
+                eToI(newStatus));
         return;
     }
 
@@ -580,7 +581,7 @@
         const std::string& physicalId,
         CameraDeviceStatus newHalStatus) {
     ALOGI("%s: Status changed for cameraId=%s, physicalCameraId=%s, newStatus=%d",
-            __FUNCTION__, id.c_str(), physicalId.c_str(), newHalStatus);
+            __FUNCTION__, id.c_str(), physicalId.c_str(), eToI(newHalStatus));
 
     StatusInternal newStatus = mapToInternal(newHalStatus);
 
@@ -596,7 +597,7 @@
     if (logicalCameraStatus != StatusInternal::PRESENT &&
             logicalCameraStatus != StatusInternal::NOT_AVAILABLE) {
         ALOGE("%s: Physical camera id %s status %d change for an invalid logical camera state %d",
-                __FUNCTION__, physicalId.c_str(), newHalStatus, logicalCameraStatus);
+                __FUNCTION__, physicalId.c_str(), eToI(newHalStatus), eToI(logicalCameraStatus));
         return;
     }
 
@@ -688,7 +689,7 @@
 void CameraService::onTorchStatusChangedLocked(const std::string& cameraId,
         TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
     ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
-            __FUNCTION__, cameraId.c_str(), newStatus);
+            __FUNCTION__, cameraId.c_str(), eToI(newStatus));
 
     TorchModeStatus status;
     status_t res = getTorchStatusLocked(cameraId, &status);
@@ -1536,7 +1537,7 @@
             s << ", " << std::to_string(i);
         }
     }
-    return std::move(s.str());
+    return s.str();
 }
 
 int32_t CameraService::mapToInterface(TorchModeStatus status) {
@@ -1552,7 +1553,7 @@
             serviceStatus = ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON;
             break;
         default:
-            ALOGW("Unknown new flash status: %d", status);
+            ALOGW("Unknown new flash status: %d", eToI(status));
     }
     return serviceStatus;
 }
@@ -1570,7 +1571,7 @@
             serviceStatus = StatusInternal::ENUMERATING;
             break;
         default:
-            ALOGW("Unknown new HAL device status: %d", status);
+            ALOGW("Unknown new HAL device status: %d", eToI(status));
     }
     return serviceStatus;
 }
@@ -1594,7 +1595,7 @@
             serviceStatus = ICameraServiceListener::STATUS_UNKNOWN;
             break;
         default:
-            ALOGW("Unknown new internal device status: %d", status);
+            ALOGW("Unknown new internal device status: %d", eToI(status));
     }
     return serviceStatus;
 }
@@ -5171,7 +5172,7 @@
     }
     if (hasAny) ret << "\n";
     ret << "]\n";
-    return std::move(ret.str());
+    return ret.str();
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
@@ -5777,7 +5778,7 @@
     }
 
     ALOGV("%s: Status has changed for camera ID %s from %#x to %#x", __FUNCTION__,
-            cameraId.c_str(), oldStatus, status);
+            cameraId.c_str(), eToI(oldStatus), eToI(status));
 
     if (oldStatus == StatusInternal::NOT_PRESENT &&
             (status != StatusInternal::PRESENT &&
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
index d23566c..1ec5072 100644
--- a/services/camera/libcameraservice/aidl/AidlUtils.cpp
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -26,6 +26,7 @@
 #include <device3/Camera3StreamInterface.h>
 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
 #include <mediautils/AImageReaderUtils.h>
+#include "utils/Utils.h"
 
 namespace android::hardware::cameraservice::utils::conversion::aidl {
 
@@ -347,8 +348,8 @@
     // Ensure the vendor ID are the same before attempting
     // anything else. If vendor IDs differ we cannot safely copy the characteristics.
     if (from.getVendorId() != to->getVendorId()) {
-        ALOGE("%s: Incompatible CameraMetadata objects. Vendor IDs differ. From: %lu; To: %lu",
-              __FUNCTION__, from.getVendorId(), to->getVendorId());
+        ALOGE("%s: Incompatible CameraMetadata objects. Vendor IDs differ. From: %" PRIu64
+              "; To: %" PRIu64, __FUNCTION__, from.getVendorId(), to->getVendorId());
         return BAD_VALUE;
     }
 
@@ -364,7 +365,7 @@
     for (size_t i = 0; i < get_camera_metadata_entry_count(src); i++) {
         int ret = get_camera_metadata_ro_entry(src, i, &entry);
         if (ret != OK) {
-            ALOGE("%s: Could not fetch entry at index %lu. Error: %d", __FUNCTION__, i, ret);
+            ALOGE("%s: Could not fetch entry at index %zu. Error: %d", __FUNCTION__, i, ret);
             from.unlock(src);
             return BAD_VALUE;
         }
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 61577e4..0d89b3e 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -420,7 +420,7 @@
         result << "    none\n";
     }
 
-    std::string resultStr = std::move(result.str());
+    std::string resultStr = result.str();
 
     write(fd, resultStr.c_str(), resultStr.size());
 
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 086a4ce..89e268c 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -40,6 +40,7 @@
 #include "common/CameraDeviceBase.h"
 #include "utils/ExifUtils.h"
 #include "utils/SessionConfigurationUtils.h"
+#include "utils/Utils.h"
 #include "HeicEncoderInfoManager.h"
 #include "HeicCompositeStream.h"
 
@@ -1466,7 +1467,7 @@
     const uint8_t *header = appSegmentBuffer + (maxSize - sizeof(CameraBlob));
     const CameraBlob *blob = (const CameraBlob*)(header);
     if (blob->blobId != CameraBlobId::JPEG_APP_SEGMENTS) {
-        ALOGE("%s: Invalid EXIF blobId %d", __FUNCTION__, blob->blobId);
+        ALOGE("%s: Invalid EXIF blobId %d", __FUNCTION__, eToI(blob->blobId));
         return 0;
     }
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 6416c11..2440c37 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -51,6 +51,7 @@
 
 #include "api2/HeicCompositeStream.h"
 #include "device3/ZoomRatioMapper.h"
+#include "utils/Utils.h"
 
 namespace android {
 
@@ -92,7 +93,7 @@
         case TorchModeStatus::AVAILABLE_ON:
             return "AVAILABLE_ON";
     }
-    ALOGW("Unexpected HAL torch mode status code %d", s);
+    ALOGW("Unexpected HAL torch mode status code %d", eToI(s));
     return "UNKNOWN_STATUS";
 }
 
@@ -105,7 +106,7 @@
         case CameraDeviceStatus::ENUMERATING:
             return "ENUMERATING";
     }
-    ALOGW("Unexpected HAL device status code %d", s);
+    ALOGW("Unexpected HAL device status code %d", eToI(s));
     return "UNKNOWN_STATUS";
 }
 
@@ -2279,7 +2280,7 @@
                         return tryToInitializeAidlProviderLocked(removedAidlProviderName,
                                 providerInfo);
                     default:
-                        ALOGE("%s Unsupported Transport %d", __FUNCTION__, providerTransport);
+                        ALOGE("%s Unsupported Transport %d", __FUNCTION__, eToI(providerTransport));
                 }
             }
         }
@@ -2366,7 +2367,7 @@
             }
             break;
         default:
-            ALOGE("%s Invalid transport %d", __FUNCTION__, transport);
+            ALOGE("%s Invalid transport %d", __FUNCTION__, eToI(transport));
             return BAD_VALUE;
     }
 
@@ -2712,7 +2713,7 @@
         }
         if (!known) {
             ALOGW("Camera provider %s says an unknown camera %s now has torch status %d. Curious.",
-                    mProviderName.c_str(), cameraDeviceName.c_str(), newStatus);
+                mProviderName.c_str(), cameraDeviceName.c_str(), eToI(newStatus));
             return;
         }
         // no lock needed since listener is set up only once during
diff --git a/services/camera/libcameraservice/common/HalConversionsTemplated.h b/services/camera/libcameraservice/common/HalConversionsTemplated.h
index 96a715c..c586062 100644
--- a/services/camera/libcameraservice/common/HalConversionsTemplated.h
+++ b/services/camera/libcameraservice/common/HalConversionsTemplated.h
@@ -19,6 +19,7 @@
 #include "common/CameraProviderManager.h"
 
 #include <device3/Camera3StreamInterface.h>
+#include <utils/Utils.h>
 
 namespace android {
 
@@ -48,7 +49,7 @@
         case HalCameraDeviceStatus::ENUMERATING:
             return CameraDeviceStatus::ENUMERATING;
     }
-    ALOGW("Unexpectedcamera device status code %d", s);
+    ALOGW("Unexpectedcamera device status code %d", eToI(s));
     return CameraDeviceStatus::NOT_PRESENT;
 }
 
@@ -74,7 +75,7 @@
         case HalTorchModeStatus::AVAILABLE_ON:
             return TorchModeStatus::AVAILABLE_ON;
     }
-    ALOGW("Unexpectedcamera torch mode status code %d", s);
+    ALOGW("Unexpectedcamera torch mode status code %d", eToI(s));
     return TorchModeStatus::NOT_AVAILABLE;
 }
 
@@ -88,7 +89,7 @@
         case HalCameraDeviceStatus::ENUMERATING:
             return "ENUMERATING";
     }
-    ALOGW("Unexpected HAL device status code %d", s);
+    ALOGW("Unexpected HAL device status code %d", eToI(s));
     return "UNKNOWN_STATUS";
 }
 
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 1e546fb..40800d9 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -26,6 +26,7 @@
 #include "device3/ZoomRatioMapper.h"
 #include <utils/SessionConfigurationUtilsHidl.h>
 #include <utils/Trace.h>
+#include <utils/Utils.h>
 
 #include <android/hardware/camera/device/3.7/ICameraDevice.h>
 
@@ -69,7 +70,7 @@
         case Status::INTERNAL_ERROR:
             return INVALID_OPERATION;
     }
-    ALOGW("Unexpected HAL status code %d", s);
+    ALOGW("Unexpected HAL status code %d", eToI(s));
     return INVALID_OPERATION;
 }
 
@@ -111,7 +112,7 @@
         case Status::INTERNAL_ERROR:
             return "INTERNAL_ERROR";
     }
-    ALOGW("Unexpected HAL status code %d", s);
+    ALOGW("Unexpected HAL status code %d", eToI(s));
     return "UNKNOWN_ERROR";
 }
 
@@ -591,7 +592,7 @@
     }
     if (status != Status::OK) {
         ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
-                __FUNCTION__, id.c_str(), statusToString(status), status);
+                __FUNCTION__, id.c_str(), statusToString(status), eToI(status));
         return;
     }
 
@@ -770,7 +771,7 @@
             if (status != Status::OK) {
                 ALOGE("%s: Unable to get physical camera %s characteristics for device %s: %s (%d)",
                         __FUNCTION__, id.c_str(), mId.c_str(),
-                        statusToString(status), status);
+                        statusToString(status), eToI(status));
                 return;
             }
 
@@ -928,7 +929,7 @@
                 res = INVALID_OPERATION;
                 break;
             default:
-                ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, callStatus);
+                ALOGE("%s: Session configuration query failed: %d", __FUNCTION__, eToI(callStatus));
                 res = UNKNOWN_ERROR;
         }
     } else {
@@ -1076,7 +1077,7 @@
                         break;
                     default:
                         ALOGE("%s: Session configuration query failed: %d", __FUNCTION__,
-                                  callStatus);
+                                eToI(callStatus));
                         res = UNKNOWN_ERROR;
                 }
             } else {
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index c42e51a..65fee7d 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -485,7 +485,7 @@
                     streamId, bufferCount);
         }
     }
-    std::string linesStr = std::move(lines.str());
+    std::string linesStr = lines.str();
     write(fd, linesStr.c_str(), linesStr.size());
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index 22d2716..61c5a3b 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -104,7 +104,7 @@
     lines << fmt::sprintf("      Total buffers: %zu, currently dequeued: %zu, "
             "currently cached: %zu\n", mTotalBufferCount, mHandoutTotalBufferCount,
             mCachedOutputBufferCount);
-    std::string linesStr = std::move(lines.str());
+    std::string linesStr = lines.str();
     write(fd, linesStr.c_str(), linesStr.size());
 
     Camera3Stream::dump(fd, args);
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 9dacaf6..09299e6 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -56,6 +56,7 @@
 #include "device3/hidl/HidlCamera3OfflineSession.h"
 #include "utils/SessionConfigurationUtilsHidl.h"
 #include "utils/TraceHFR.h"
+#include "utils/Utils.h"
 
 #include "../../common/hidl/HidlProviderInfo.h"
 #include "HidlCamera3Device.h"
@@ -881,7 +882,7 @@
                     ret = true;
                     break;
                 default:
-                    ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, callStatus);
+                    ALOGV("%s: Reconfiguration query failed: %d", __FUNCTION__, eToI(callStatus));
                     ret = true;
             }
         } else {
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-0 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..4c56959
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-1 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..fc0e371
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-10 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-10
new file mode 100644
index 0000000..1266b3e
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-10
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-11 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-11
new file mode 100644
index 0000000..cb1c0e4
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-11
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-12 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-12
new file mode 100644
index 0000000..ab820a4
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-12
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-13 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-13
new file mode 100644
index 0000000..6051e9a
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-13
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-14 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-14
new file mode 100644
index 0000000..596e55b
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-14
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-15 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-15
new file mode 100644
index 0000000..20d7dcb
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-15
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-2 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..5bbfa56
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-3 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..cd148f6
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-4 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-4
new file mode 100644
index 0000000..e4ddb50
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-4
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-5 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-5
new file mode 100644
index 0000000..3be3ce1
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-5
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-6 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-6
new file mode 100644
index 0000000..3b51e41
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-6
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-7 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-7
new file mode 100644
index 0000000..3b929df
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-7
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-8 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-8
new file mode 100644
index 0000000..f92337b
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-8
Binary files differ
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-9 b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-9
new file mode 100644
index 0000000..0fe0f06
--- /dev/null
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/corpus/seed-2024-08-29-9
Binary files differ
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index 55e2c9d..d49aad6 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -44,13 +44,25 @@
         "libjpeg",
         "liblog",
         "libutils",
-        "camera_platform_flags_c_lib",
     ],
 
     static_libs: [
         "libgmock",
     ],
 
+    target: {
+        android: {
+            shared_libs: [
+                "camera_platform_flags_c_lib",
+            ],
+        },
+        host: {
+            shared_libs: [
+                "camera_platform_flags_c_lib_for_test",
+            ],
+        },
+    },
+
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index d5e3790..85bca6f 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -268,6 +268,12 @@
             const auto& gbps = config.getGraphicBufferProducers();
             int32_t width = 0, height = 0;
             if (gbps.size() > 0) {
+                if (gbps[0] == nullptr) {
+                    ALOGE("%s: Failed to query size due to abandoned surface.",
+                            __FUNCTION__);
+                    return CameraFeatureCombinationStats::CAMERA_FEATURE_UNKNOWN;
+                }
+
                 sp<Surface> surface = new Surface(gbps[0], /*useAsync*/false);
                 ANativeWindow *anw = surface.get();
 
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
index cfa1815..9986a84 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
@@ -23,6 +23,7 @@
 #include "device3/aidl/AidlCamera3Device.h"
 #include "device3/hidl/HidlCamera3Device.h"
 #include "device3/Camera3OutputStream.h"
+#include "utils/Utils.h"
 
 using android::camera3::OutputStreamInfo;
 using android::hardware::camera2::ICameraDeviceUser;
@@ -48,16 +49,16 @@
     hidl.streams.resize(aidl.streams.size());
     size_t i = 0;
     for (const auto &stream : aidl.streams) {
-        if (static_cast<int>(stream.dynamicRangeProfile) !=
+        if (eToI(stream.dynamicRangeProfile) !=
                 ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD) {
             ALOGE("%s Dynamic range profile %" PRId64 " not supported by HIDL", __FUNCTION__,
-                    stream.dynamicRangeProfile);
+                    eToI(stream.dynamicRangeProfile));
             return BAD_VALUE;
         }
 
-        if (static_cast<int>(stream.useCase) != ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
+        if (eToI(stream.useCase) != ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT) {
             ALOGE("%s Stream use case %" PRId64 "not supported by HIDL", __FUNCTION__,
-                    stream.useCase);
+                    eToI(stream.useCase));
             return BAD_VALUE;
         }
 
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index 38de93a..5258c0e 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -384,7 +384,7 @@
         }
         returnStr << "]\n";
     }
-    return std::move(returnStr.str());
+    return returnStr.str();
 }
 
 template<typename T>
diff --git a/services/camera/libcameraservice/utils/Utils.h b/services/camera/libcameraservice/utils/Utils.h
index 4e90871..0eb5e2c 100644
--- a/services/camera/libcameraservice/utils/Utils.h
+++ b/services/camera/libcameraservice/utils/Utils.h
@@ -19,10 +19,21 @@
 
 #include <sched.h>
 #include <unistd.h>
+#include <type_traits>
 
 namespace android {
 
 /**
+ * Magically convert an enum to its underlying integer type, mostly so they can be
+ * printed with printf-style formatters without warnings.
+ * Backport of C++23 std::to_underlying()
+ */
+template<typename Enum>
+constexpr std::underlying_type_t<Enum> eToI(Enum val) {
+    return static_cast<std::underlying_type_t<Enum>>(val);
+}
+
+/**
  * As of Android V, ro.board.api_level returns the year and month of release (ex. 202404)
  * instead of release SDK version. This function maps year/month format back to release
  * SDK version.
diff --git a/services/camera/virtualcamera/util/JpegUtil.h b/services/camera/virtualcamera/util/JpegUtil.h
index 184dd56..0a8df90 100644
--- a/services/camera/virtualcamera/util/JpegUtil.h
+++ b/services/camera/virtualcamera/util/JpegUtil.h
@@ -18,6 +18,7 @@
 #define ANDROID_COMPANION_VIRTUALCAMERA_JPEGUTIL_H
 
 #include <optional>
+#include <vector>
 
 #include "android/hardware_buffer.h"
 #include "util/Util.h"
diff --git a/services/medialog/Android.bp b/services/medialog/Android.bp
index fdb56e5..7a4c3ad 100644
--- a/services/medialog/Android.bp
+++ b/services/medialog/Android.bp
@@ -29,6 +29,8 @@
         "packagemanager_aidl-cpp",
     ],
 
+    export_include_dirs: ["."],
+
     cflags: [
         "-Wall",
         "-Werror",
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-0 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-0
new file mode 100644
index 0000000..802c2b5
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-0
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-1 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-1
new file mode 100644
index 0000000..9ee6a15
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-1
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-10 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-10
new file mode 100644
index 0000000..95006c8
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-10
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-11 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-11
new file mode 100644
index 0000000..853be96
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-11
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-12 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-12
new file mode 100644
index 0000000..c3e9848
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-12
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-13 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-13
new file mode 100644
index 0000000..08b7f0d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-13
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-14 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-14
new file mode 100644
index 0000000..20e5e80
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-14
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-15 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-15
new file mode 100644
index 0000000..4e54f0b
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-15
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-2 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-2
new file mode 100644
index 0000000..2b2495d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-2
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-3 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-3
new file mode 100644
index 0000000..753594d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-3
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-4 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-4
new file mode 100644
index 0000000..0ed2010
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-4
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-5 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-5
new file mode 100644
index 0000000..f6141d1
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-5
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-6 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-6
new file mode 100644
index 0000000..b93f618
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-6
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-7 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-7
new file mode 100644
index 0000000..f8f296d
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-7
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-8 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-8
new file mode 100644
index 0000000..29bdbc1
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-8
Binary files differ
diff --git a/services/mediametrics/fuzzer/corpus/seed-2024-08-29-9 b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-9
new file mode 100644
index 0000000..315f25e
--- /dev/null
+++ b/services/mediametrics/fuzzer/corpus/seed-2024-08-29-9
Binary files differ
diff --git a/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
index c7468c7..572e969 100644
--- a/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
+++ b/services/mediametrics/fuzzer/mediametrics_aidl_fuzzer.cpp
@@ -22,6 +22,7 @@
 using ::android::MediaMetricsService;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    signal(SIGPIPE, SIG_IGN);
     auto service = sp<MediaMetricsService>::make();
     fuzzService(service, FuzzedDataProvider(data, size));
     return 0;
diff --git a/services/mediaresourcemanager/ResourceManagerMetrics.cpp b/services/mediaresourcemanager/ResourceManagerMetrics.cpp
index a8a1de1..8b3711c 100644
--- a/services/mediaresourcemanager/ResourceManagerMetrics.cpp
+++ b/services/mediaresourcemanager/ResourceManagerMetrics.cpp
@@ -821,7 +821,7 @@
     metricsLog += getAppsPixelCount(mProcessPixelsMap);
     metricsLog += getAppsCodecUsageMetrics(mProcessConcurrentCodecsMap);
 
-    return std::move(metricsLog);
+    return metricsLog;
 }
 
 } // namespace android
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 9c2fb7c..f12a5d6 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -310,6 +310,7 @@
     mServiceLog->add(log);
 
     std::scoped_lock lock{mLock};
+    ClientInfoParcel updatedClientInfo = clientInfo;
     if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
         pid_t callingPid = IPCThreadState::self()->getCallingPid();
         uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -317,6 +318,8 @@
                 __FUNCTION__, pid, uid, callingPid, callingUid);
         pid = callingPid;
         uid = callingUid;
+        updatedClientInfo.pid = callingPid;
+        updatedClientInfo.uid = callingUid;
     }
     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
     ResourceInfo& info = getResourceInfoForEdit(clientInfo, client, infos);
@@ -342,7 +345,7 @@
     }
     if (info.deathNotifier == nullptr && client != nullptr) {
         info.deathNotifier = DeathNotifier::Create(
-            client, ref<ResourceManagerService>(), clientInfo);
+            client, ref<ResourceManagerService>(), updatedClientInfo);
     }
     if (mObserverService != nullptr && !resourceAdded.empty()) {
         mObserverService->onResourceAdded(uid, pid, resourceAdded);
diff --git a/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp b/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp
index 679ab13..49f68e9 100644
--- a/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp
+++ b/services/mediaresourcemanager/ResourceManagerServiceUtils.cpp
@@ -94,7 +94,7 @@
         str.append("\n");
     }
 
-    return std::move(str);
+    return str;
 }
 
 bool ResourceList::operator==(const ResourceList& rhs) const {
diff --git a/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
index 6253df7..1cad482 100644
--- a/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
@@ -26,6 +26,7 @@
 using ndk::SharedRefBase;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+   signal(SIGPIPE, SIG_IGN);
    std::shared_ptr<ResourceManagerService> service = ResourceManagerService::Create();
    fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
    return 0;
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index e3601a1..67b319f 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -84,6 +84,7 @@
     shared_libs: [
         "aaudio-aidl-cpp",
         "com.android.media.aaudio-aconfig-cc",
+        "com.android.media.aaudio-aconfig-cc",
         "framework-permission-aidl-cpp",
         "libaaudio_internal",
         "libaudioclient",
@@ -157,6 +158,8 @@
         "frameworks/av/media/libnbaio/include_mono",
     ],
 
+    export_include_dirs: ["."],
+
     tidy: true,
     tidy_checks: tidy_errors,
     tidy_checks_as_errors: tidy_errors,