Turn off overrideToPortrait where not needed. am: 7b14d5e6c4

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

Change-Id: Ib180c20f7abe08e708fe8f8743a125b4c5675f69
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index ee609e1..37f6457 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,7 @@
     srcs: [
         "aidl/android/media/InterpolatorConfig.aidl",
         "aidl/android/media/InterpolatorType.aidl",
-        "aidl/android/media/MicrophoneInfoData.aidl",
+        "aidl/android/media/MicrophoneInfoFw.aidl",
         "aidl/android/media/VolumeShaperConfiguration.aidl",
         "aidl/android/media/VolumeShaperConfigurationOptionFlag.aidl",
         "aidl/android/media/VolumeShaperConfigurationType.aidl",
@@ -52,16 +52,22 @@
         "aidl/android/media/VolumeShaperOperationFlag.aidl",
         "aidl/android/media/VolumeShaperState.aidl",
     ],
+    imports: [
+        "android.media.audio.common.types-V2",
+    ],
     backend: {
         cpp: {
             min_sdk_version: "29",
             apex_available: [
                 "//apex_available:platform",
-                "com.android.bluetooth",
+                "com.android.btservices",
                 "com.android.media",
                 "com.android.media.swcodec",
             ],
         },
+        java: {
+            sdk_version: "module_current",
+        },
     },
 }
 
@@ -75,10 +81,10 @@
         "av-types-aidl-cpp",
     ],
     header_libs: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     export_header_lib_headers: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     host_supported: true,
     vendor_available: true,
@@ -86,7 +92,7 @@
     min_sdk_version: "29",
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/MainlineFiles.cfg b/MainlineFiles.cfg
index 490bbbf..bf39c1a 100644
--- a/MainlineFiles.cfg
+++ b/MainlineFiles.cfg
@@ -21,11 +21,20 @@
 #
 # matching is purely prefix
 # so 'foo' will match 'foo', 'foo.c', 'foo/bar/baz'
-# if you want to exclude a directory, best to use a pattern like "foo/"
+# if you want to specify a directory, best to use a pattern like "foo/"
 #
 
+apex/
 media/codec2/components/
-media/codecs/
-media/extractors/
-media/libstagefright/mpeg2ts/
-media/libstagefright/flac/
+media/codec2/core/
+media/codec2/hidl/
+media/codec2/sfplugin/utils/
+media/codec2/vndk/
+media/libstagefright/data/media_codecs_sw.xml
+media/module/
+services/mediacodec/
+
+# source code used in both framework and mainline libraries
+media/libstagefright/HevcUtils.cpp
+media/libstagefright/MediaSource.cpp
+media/libstagefright/Utils.cpp
diff --git a/OWNERS b/OWNERS
index 40c65e7..3c7a3ab 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,7 +1,16 @@
-# Bug component: 1344
+## Media team top-level OWNERS, bug component: 1344
+## Only contact for camera changes as a fallback
 elaurent@google.com
-etalvala@google.com
 lajos@google.com
 
 # go/android-fwk-media-solutions for info on areas of ownership.
 include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
+
+## Camera team top-level OWNERS, bug component: 41727
+## Only contact for media changes as a fallback
+etalvala@google.com
+shuzhenwang@google.com
+
+# mainline related
+per-file MainlineFiles.cfg=essick@google.com
+per-file MainlineFiles.cfg=file:/media/janitors/reliability_mainline_OWNERS
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 716b550..1f7083b 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -11,3 +11,4 @@
 clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
                media/libmediatranscoding/
                services/mediatranscoding/
+               media/libaudioclient/tests/
diff --git a/aidl/android/media/MicrophoneInfoData.aidl b/aidl/android/media/MicrophoneInfoData.aidl
deleted file mode 100644
index 747bfa5..0000000
--- a/aidl/android/media/MicrophoneInfoData.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * {@hide}
- */
-parcelable MicrophoneInfoData {
-    @utf8InCpp String deviceId;
-    int portId;
-    int type;
-    @utf8InCpp String address;
-    int deviceLocation;
-    int deviceGroup;
-    int indexInTheGroup;
-    float[] geometricLocation;
-    float[] orientation;
-    float[] frequencies;
-    float[] frequencyResponses;
-    int[] channelMapping;
-    float sensitivity;
-    float maxSpl;
-    float minSpl;
-    int directionality;
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl b/aidl/android/media/MicrophoneInfoFw.aidl
similarity index 69%
copy from media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
copy to aidl/android/media/MicrophoneInfoFw.aidl
index 3a4ca31..bad0e0a 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
+++ b/aidl/android/media/MicrophoneInfoFw.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,13 +16,14 @@
 
 package android.media;
 
-import android.media.AudioPortConfigSys;
-import android.media.audio.common.AudioPortConfig;
+import android.media.audio.common.MicrophoneDynamicInfo;
+import android.media.audio.common.MicrophoneInfo;
 
 /**
  * {@hide}
  */
-parcelable AudioPortConfig {
-    AudioPortConfig hal;
-    AudioPortConfigSys sys;
+parcelable MicrophoneInfoFw {
+    MicrophoneInfo info;
+    MicrophoneDynamicInfo dynamic;
+    int portId;
 }
diff --git a/apex/Android.bp b/apex/Android.bp
index 570ca01..b0d7c02 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -67,13 +67,15 @@
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media-androidManifest",
 
-    // IMPORTANT: q-launched-apex-module enables the build system to make
-    // sure the package compatible to Android 10 in two ways:
+    // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+    // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+    // is set):
     // - build the APEX package compatible to Android 10
     //   so that the package can be installed.
     // - build artifacts (lib/javalib/bin) against Android 10 SDK
     //   so that the artifacts can run.
-    defaults: ["q-launched-apex-module"],
+    // If the flag is not set, the package is built to be compatible with Android 12.
+    defaults: ["q-launched-dcla-enabled-apex-module"],
     // Indicates that pre-installed version of this apex can be compressed.
     // Whether it actually will be compressed is controlled on per-device basis.
     compressible: true,
@@ -191,13 +193,15 @@
     // Use a custom AndroidManifest.xml used for API targeting.
     androidManifest: ":com.android.media.swcodec-androidManifest",
 
-    // IMPORTANT: q-launched-apex-module enables the build system to make
-    // sure the package compatible to Android 10 in two ways:
+    // IMPORTANT: q-launched-dcla-enabled-apex-module enables the build system to make
+    // sure the package compatible to Android 10 in two ways(if flag APEX_BUILD_FOR_PRE_S_DEVICES=1
+    // is set):
     // - build the APEX package compatible to Android 10
     //   so that the package can be installed.
     // - build artifacts (lib/javalib/bin) against Android 10 SDK
     //   so that the artifacts can run.
-    defaults: ["q-launched-apex-module"],
+    // If the flag is not set, the package is built to be compatible with Android 12.
+    defaults: ["q-launched-dcla-enabled-apex-module"],
     // Indicates that pre-installed version of this apex can be compressed.
     // Whether it actually will be compressed is controlled on per-device basis.
     compressible: true,
diff --git a/apex/ld.config.txt b/apex/ld.config.txt
index 713f0b7..4dc5fb1 100644
--- a/apex/ld.config.txt
+++ b/apex/ld.config.txt
@@ -33,7 +33,7 @@
 # TODO: replace the following when apex has a way to auto-generate this list
 # namespace.default.link.platform.shared_libs  = %LLNDK_LIBRARIES%
 # namespace.default.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
+namespace.default.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libdl_android.so:libvulkan.so:libbinder_ndk.so
 
 ###############################################################################
 # "platform" namespace
@@ -138,7 +138,7 @@
 # TODO: replace the following when apex has a way to auto-generate this list
 # namespace.sphal.link.platform.shared_libs  = %LLNDK_LIBRARIES%
 # namespace.sphal.link.platform.shared_libs += %SANITIZER_RUNTIME_LIBRARIES%
-namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libRS.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
+namespace.sphal.link.platform.shared_libs = libEGL.so:libGLESv1_CM.so:libGLESv2.so:libGLESv3.so:libandroid_net.so:libc.so:libcgrouprc.so:libclang_rt.asan-aarch64-android.so:libclang_rt.asan-arm-android.so:libclang_rt.hwasan-aarch64-android.so:libclang_rt.asan-i686-android.so:libclang_rt.asan-x86_64-android.so:libdl.so:libft2.so:liblog.so:libm.so:libmediandk.so:libnativewindow.so:libneuralnetworks.so:libsync.so:libvndksupport.so:libvulkan.so:libbinder_ndk.so
 
 # Add a link for libz.so which is llndk on devices where VNDK is not enforced.
 namespace.sphal.link.platform.shared_libs += libz.so
diff --git a/apex/manifest.json b/apex/manifest.json
index 1a26bff..5b235cd 100644
--- a/apex/manifest.json
+++ b/apex/manifest.json
@@ -1,6 +1,10 @@
 {
   "name": "com.android.media",
-  "version": 330400000,
+
+  // Placeholder module version to be replaced during build.
+  // Do not change!
+  "version": 0,
+
   "requireNativeLibs": [
     "libandroid.so",
     "libbinder_ndk.so",
diff --git a/apex/manifest_codec.json b/apex/manifest_codec.json
index 9426e59..f2b8b36 100644
--- a/apex/manifest_codec.json
+++ b/apex/manifest_codec.json
@@ -1,6 +1,10 @@
 {
   "name": "com.android.media.swcodec",
-  "version": 330400000,
+
+  // Placeholder module version to be replaced during build.
+  // Do not change!
+  "version": 0,
+
   "requireNativeLibs": [
     ":sphal"
   ]
diff --git a/camera/OWNERS b/camera/OWNERS
index 385c163..b705548 100644
--- a/camera/OWNERS
+++ b/camera/OWNERS
@@ -1,7 +1,11 @@
 # Bug component: 41727
 etalvala@google.com
 arakesh@google.com
+borgera@google.com
+bkukreja@google.com
 epeev@google.com
 jchowdhary@google.com
-shuzhenwang@google.com
+rdhanjal@google.com
 ruchamk@google.com
+shuzhenwang@google.com
+
diff --git a/camera/ndk/include/camera/NdkCameraDevice.h b/camera/ndk/include/camera/NdkCameraDevice.h
index 7be4bd3..239cb31 100644
--- a/camera/ndk/include/camera/NdkCameraDevice.h
+++ b/camera/ndk/include/camera/NdkCameraDevice.h
@@ -470,18 +470,6 @@
  *   <a href="http://developer.android.com/reference/android/media/CamcorderProfile.html">
  *    CamcorderProfiles</a>.</li>
  *
- * <li>For efficient YUV processing with <a href=
- *   "http://developer.android.com/reference/android/renderscript/package-summary.html">
- *   RenderScript</a>:
- *   Create a RenderScript
- *   <a href="http://developer.android.com/reference/android/renderscript/Allocation.html">
- *   Allocation</a> with a supported YUV
- *   type, the IO_INPUT flag, and one of the YUV output sizes returned by
- *   {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS},
- *   Then obtain the Surface with
- *   <a href="http://developer.android.com/reference/android/renderscript/Allocation.html#getSurface()">
- *   Allocation#getSurface}</a>.</li>
- *
  * <li>For access to RAW, uncompressed YUV, or compressed JPEG data in the application: Create an
  *   {@link AImageReader} object using the {@link AImageReader_new} method with one of the supported
  *   output formats given by {@link ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS}. Then obtain a
diff --git a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
index 77c934a..bb4ef56 100644
--- a/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
+++ b/camera/ndk/ndk_vendor/impl/ACameraManager.cpp
@@ -165,7 +165,10 @@
     Mutex::Autolock _l(mLock);
     if (mCameraService != nullptr) {
         mCameraService->unlinkToDeath(mDeathNotifier);
-        mCameraService->removeListener(mCameraServiceListener);
+        auto stat = mCameraService->removeListener(mCameraServiceListener);
+        if (!stat.isOk()) {
+            ALOGE("Failed to remove listener to camera service %s", stat.description().c_str());
+        }
     }
     mDeathNotifier.clear();
     if (mCbLooper != nullptr) {
@@ -475,6 +478,10 @@
                 ALOGE("%s: Cannot find camera callback fp!", __FUNCTION__);
                 return;
             }
+            if (cb == nullptr) {
+                // Physical camera callback is null
+                return;
+            }
             found = msg->findPointer(kContextKey, &context);
             if (!found) {
                 ALOGE("%s: Cannot find callback context!", __FUNCTION__);
diff --git a/cmds/stagefright/Android.bp b/cmds/stagefright/Android.bp
index e1fe07e..445541e 100644
--- a/cmds/stagefright/Android.bp
+++ b/cmds/stagefright/Android.bp
@@ -211,46 +211,6 @@
 }
 
 cc_binary {
-    name: "mediafilter",
-
-    srcs: [
-        "filters/argbtorgba.rscript",
-        "filters/nightvision.rscript",
-        "filters/saturation.rscript",
-        "mediafilter.cpp",
-    ],
-
-    header_libs: [
-        "libmediadrm_headers",
-        "libmediametrics_headers",
-        "libstagefright_headers",
-        "rs-headers",
-    ],
-
-    shared_libs: [
-        "libstagefright",
-        "liblog",
-        "libutils",
-        "libbinder",
-        "libstagefright_foundation",
-        "libmedia_omx",
-        "libui",
-        "libgui",
-        "libRScpp",
-    ],
-
-    static_libs: ["libstagefright_mediafilter"],
-
-    cflags: [
-        "-Wno-multichar",
-    ],
-
-    sanitize: {
-        cfi: true,
-    },
-}
-
-cc_binary {
     name: "muxer",
 
     srcs: ["muxer.cpp"],
diff --git a/cmds/stagefright/SineSource.cpp b/cmds/stagefright/SineSource.cpp
index 0ecc16c..0656030 100644
--- a/cmds/stagefright/SineSource.cpp
+++ b/cmds/stagefright/SineSource.cpp
@@ -63,12 +63,15 @@
         MediaBufferBase **out, const ReadOptions * /* options */) {
     *out = NULL;
 
-    MediaBufferBase *buffer;
+    MediaBufferBase *buffer = nullptr;
     status_t err = mGroup->acquire_buffer(&buffer);
 
     if (err != OK) {
         return err;
     }
+    if (buffer == nullptr) {
+        return AMEDIA_ERROR_UNKNOWN;
+    }
 
     size_t frameSize = mNumChannels * sizeof(int16_t);
     size_t numFramesPerBuffer = buffer->size() / frameSize;
diff --git a/cmds/stagefright/filters/argbtorgba.rscript b/cmds/stagefright/filters/argbtorgba.rscript
deleted file mode 100644
index 229ff8c..0000000
--- a/cmds/stagefright/filters/argbtorgba.rscript
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
-    v_out->x = v_in->y;
-    v_out->y = v_in->z;
-    v_out->z = v_in->w;
-    v_out->w = v_in->x;
-}
\ No newline at end of file
diff --git a/cmds/stagefright/filters/nightvision.rscript b/cmds/stagefright/filters/nightvision.rscript
deleted file mode 100644
index f61413c..0000000
--- a/cmds/stagefright/filters/nightvision.rscript
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-const static float3 gNightVisionMult = {0.5f, 1.f, 0.5f};
-
-// calculates luminance of pixel, then biases color balance toward green
-void root(const uchar4 *v_in, uchar4 *v_out) {
-    v_out->x = v_in->x; // don't modify A
-
-    // get RGB, scale 0-255 uchar to 0-1.0 float
-    float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
-            v_in->w * 0.003921569f};
-
-    // apply filter
-    float3 result = dot(rgb, gMonoMult) * gNightVisionMult;
-
-    v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
-    v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
-    v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/cmds/stagefright/filters/saturation.rscript b/cmds/stagefright/filters/saturation.rscript
deleted file mode 100644
index 1de9dd8..0000000
--- a/cmds/stagefright/filters/saturation.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
-    v_out->x = v_in->x; // don't modify A
-
-    // get RGB, scale 0-255 uchar to 0-1.0 float
-    float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
-            v_in->w * 0.003921569f};
-
-    // apply saturation filter
-    float3 result = dot(rgb, gMonoMult);
-    result = mix(result, rgb, gSaturation);
-
-    v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
-    v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
-    v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/cmds/stagefright/mediafilter.cpp b/cmds/stagefright/mediafilter.cpp
deleted file mode 100644
index 67c68e6..0000000
--- a/cmds/stagefright/mediafilter.cpp
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "mediafilterTest"
-
-#include <inttypes.h>
-
-#include <binder/ProcessState.h>
-#include <filters/ColorConvert.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <gui/Surface.h>
-#include <media/IMediaHTTPService.h>
-#include <media/MediaCodecBuffer.h>
-#include <mediadrm/ICrypto.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaCodec.h>
-#include <media/stagefright/NuMediaExtractor.h>
-#include <media/stagefright/RenderScriptWrapper.h>
-#include <OMX_IVCommon.h>
-#include <ui/DisplayMode.h>
-
-#include "RenderScript.h"
-#include "ScriptC_argbtorgba.h"
-#include "ScriptC_nightvision.h"
-#include "ScriptC_saturation.h"
-
-// test parameters
-static const bool kTestFlush = true;        // Note: true will drop 1 out of
-static const int kFlushAfterFrames = 25;    // kFlushAfterFrames output frames
-static const int64_t kTimeout = 500ll;
-
-// built-in filter parameters
-static const int32_t kInvert = false;   // ZeroFilter param
-static const float kBlurRadius = 15.0f; // IntrinsicBlurFilter param
-static const float kSaturation = 0.0f;  // SaturationFilter param
-
-static void usage(const char *me) {
-    fprintf(stderr, "usage: [flags] %s\n"
-                    "\t[-b] use IntrinsicBlurFilter\n"
-                    "\t[-c] use argb to rgba conversion RSFilter\n"
-                    "\t[-n] use night vision RSFilter\n"
-                    "\t[-r] use saturation RSFilter\n"
-                    "\t[-s] use SaturationFilter\n"
-                    "\t[-z] use ZeroFilter (copy filter)\n"
-                    "\t[-R] render output to surface (enables -S)\n"
-                    "\t[-S] allocate buffers from a surface\n"
-                    "\t[-T] use render timestamps (enables -R)\n",
-                    me);
-    exit(1);
-}
-
-namespace android {
-
-struct SaturationRSFilter : RenderScriptWrapper::RSFilterCallback {
-    void init(const RSC::sp<RSC::RS> &context) {
-        mScript = new ScriptC_saturation(context);
-        mScript->set_gSaturation(3.f);
-    }
-
-    virtual status_t processBuffers(
-            RSC::Allocation *inBuffer, RSC::Allocation *outBuffer) {
-        mScript->forEach_root(inBuffer, outBuffer);
-
-        return OK;
-    }
-
-    status_t handleSetParameters(const sp<AMessage> &msg __unused) {
-        return OK;
-    }
-
-private:
-    RSC::sp<ScriptC_saturation> mScript;
-};
-
-struct NightVisionRSFilter : RenderScriptWrapper::RSFilterCallback {
-    void init(const RSC::sp<RSC::RS> &context) {
-        mScript = new ScriptC_nightvision(context);
-    }
-
-    virtual status_t processBuffers(
-            RSC::Allocation *inBuffer, RSC::Allocation *outBuffer) {
-        mScript->forEach_root(inBuffer, outBuffer);
-
-        return OK;
-    }
-
-    status_t handleSetParameters(const sp<AMessage> &msg __unused) {
-        return OK;
-    }
-
-private:
-    RSC::sp<ScriptC_nightvision> mScript;
-};
-
-struct ARGBToRGBARSFilter : RenderScriptWrapper::RSFilterCallback {
-    void init(const RSC::sp<RSC::RS> &context) {
-        mScript = new ScriptC_argbtorgba(context);
-    }
-
-    virtual status_t processBuffers(
-            RSC::Allocation *inBuffer, RSC::Allocation *outBuffer) {
-        mScript->forEach_root(inBuffer, outBuffer);
-
-        return OK;
-    }
-
-    status_t handleSetParameters(const sp<AMessage> &msg __unused) {
-        return OK;
-    }
-
-private:
-    RSC::sp<ScriptC_argbtorgba> mScript;
-};
-
-struct CodecState {
-    sp<MediaCodec> mCodec;
-    Vector<sp<MediaCodecBuffer> > mInBuffers;
-    Vector<sp<MediaCodecBuffer> > mOutBuffers;
-    bool mSignalledInputEOS;
-    bool mSawOutputEOS;
-    int64_t mNumBuffersDecoded;
-};
-
-struct DecodedFrame {
-    size_t index;
-    size_t offset;
-    size_t size;
-    int64_t presentationTimeUs;
-    uint32_t flags;
-};
-
-enum FilterType {
-    FILTERTYPE_ZERO,
-    FILTERTYPE_INTRINSIC_BLUR,
-    FILTERTYPE_SATURATION,
-    FILTERTYPE_RS_SATURATION,
-    FILTERTYPE_RS_NIGHT_VISION,
-    FILTERTYPE_RS_ARGB_TO_RGBA,
-};
-
-size_t inputFramesSinceFlush = 0;
-void tryCopyDecodedBuffer(
-        List<DecodedFrame> *decodedFrameIndices,
-        CodecState *filterState,
-        CodecState *vidState) {
-    if (decodedFrameIndices->empty()) {
-        return;
-    }
-
-    size_t filterIndex;
-    status_t err = filterState->mCodec->dequeueInputBuffer(
-            &filterIndex, kTimeout);
-    if (err != OK) {
-        return;
-    }
-
-    ++inputFramesSinceFlush;
-
-    DecodedFrame frame = *decodedFrameIndices->begin();
-
-    // only consume a buffer if we are not going to flush, since we expect
-    // the dequeue -> flush -> queue operation to cause an error and
-    // not produce an output frame
-    if (!kTestFlush || inputFramesSinceFlush < kFlushAfterFrames) {
-        decodedFrameIndices->erase(decodedFrameIndices->begin());
-    }
-    size_t outIndex = frame.index;
-
-    const sp<MediaCodecBuffer> &srcBuffer =
-        vidState->mOutBuffers.itemAt(outIndex);
-    const sp<MediaCodecBuffer> &destBuffer =
-        filterState->mInBuffers.itemAt(filterIndex);
-
-    sp<AMessage> srcFormat, destFormat;
-    vidState->mCodec->getOutputFormat(&srcFormat);
-    filterState->mCodec->getInputFormat(&destFormat);
-
-    int32_t srcWidth, srcHeight, srcStride, srcSliceHeight;
-    int32_t srcColorFormat, destColorFormat;
-    int32_t destWidth, destHeight, destStride, destSliceHeight;
-    CHECK(srcFormat->findInt32("stride", &srcStride)
-            && srcFormat->findInt32("slice-height", &srcSliceHeight)
-            && srcFormat->findInt32("width", &srcWidth)
-            && srcFormat->findInt32("height", & srcHeight)
-            && srcFormat->findInt32("color-format", &srcColorFormat));
-    CHECK(destFormat->findInt32("stride", &destStride)
-            && destFormat->findInt32("slice-height", &destSliceHeight)
-            && destFormat->findInt32("width", &destWidth)
-            && destFormat->findInt32("height", & destHeight)
-            && destFormat->findInt32("color-format", &destColorFormat));
-
-    CHECK(srcWidth <= destStride && srcHeight <= destSliceHeight);
-
-    convertYUV420spToARGB(
-            srcBuffer->data(),
-            srcBuffer->data() + srcStride * srcSliceHeight,
-            srcWidth,
-            srcHeight,
-            destBuffer->data());
-
-    // copy timestamp
-    int64_t timeUs;
-    CHECK(srcBuffer->meta()->findInt64("timeUs", &timeUs));
-    destBuffer->meta()->setInt64("timeUs", timeUs);
-
-    if (kTestFlush && inputFramesSinceFlush >= kFlushAfterFrames) {
-        inputFramesSinceFlush = 0;
-
-        // check that queueing a buffer that was dequeued before flush
-        // fails with expected error EACCES
-        filterState->mCodec->flush();
-
-        err = filterState->mCodec->queueInputBuffer(
-                filterIndex, 0 /* offset */, destBuffer->size(),
-                timeUs, frame.flags);
-
-        if (err == OK) {
-            ALOGE("FAIL: queue after flush returned OK");
-        } else if (err != -EACCES) {
-            ALOGE("queueInputBuffer after flush returned %d, "
-                    "expected -EACCES (-13)", err);
-        }
-    } else {
-        err = filterState->mCodec->queueInputBuffer(
-                filterIndex, 0 /* offset */, destBuffer->size(),
-                timeUs, frame.flags);
-        CHECK(err == OK);
-
-        err = vidState->mCodec->releaseOutputBuffer(outIndex);
-        CHECK(err == OK);
-    }
-}
-
-size_t outputFramesSinceFlush = 0;
-void tryDrainOutputBuffer(
-        CodecState *filterState,
-        const sp<Surface> &surface, bool renderSurface,
-        bool useTimestamp, int64_t *startTimeRender) {
-    size_t index;
-    size_t offset;
-    size_t size;
-    int64_t presentationTimeUs;
-    uint32_t flags;
-    status_t err = filterState->mCodec->dequeueOutputBuffer(
-            &index, &offset, &size, &presentationTimeUs, &flags,
-            kTimeout);
-
-    if (err != OK) {
-        return;
-    }
-
-    ++outputFramesSinceFlush;
-
-    if (kTestFlush && outputFramesSinceFlush >= kFlushAfterFrames) {
-        filterState->mCodec->flush();
-    }
-
-    if (surface == NULL || !renderSurface) {
-        err = filterState->mCodec->releaseOutputBuffer(index);
-    } else if (useTimestamp) {
-        if (*startTimeRender == -1) {
-            // begin rendering 2 vsyncs after first decode
-            *startTimeRender = systemTime(SYSTEM_TIME_MONOTONIC)
-                    + 33000000 - (presentationTimeUs * 1000);
-        }
-        presentationTimeUs =
-                (presentationTimeUs * 1000) + *startTimeRender;
-        err = filterState->mCodec->renderOutputBufferAndRelease(
-                index, presentationTimeUs);
-    } else {
-        err = filterState->mCodec->renderOutputBufferAndRelease(index);
-    }
-
-    if (kTestFlush && outputFramesSinceFlush >= kFlushAfterFrames) {
-        outputFramesSinceFlush = 0;
-
-        // releasing the buffer dequeued before flush should cause an error
-        // if so, the frame will also be skipped in output stream
-        if (err == OK) {
-            ALOGE("FAIL: release after flush returned OK");
-        } else if (err != -EACCES) {
-            ALOGE("releaseOutputBuffer after flush returned %d, "
-                    "expected -EACCES (-13)", err);
-        }
-    } else {
-        CHECK(err == OK);
-    }
-
-    if (flags & MediaCodec::BUFFER_FLAG_EOS) {
-        ALOGV("reached EOS on output.");
-        filterState->mSawOutputEOS = true;
-    }
-}
-
-static int decode(
-        const sp<android::ALooper> &looper,
-        const char *path,
-        const sp<Surface> &surface,
-        bool renderSurface,
-        bool useTimestamp,
-        FilterType filterType) {
-
-    static int64_t kTimeout = 500ll;
-
-    sp<NuMediaExtractor> extractor = new NuMediaExtractor(NuMediaExtractor::EntryPoint::OTHER);
-
-    if (extractor->setDataSource(NULL /* httpService */, path) != OK) {
-        fprintf(stderr, "unable to instantiate extractor.\n");
-        return 1;
-    }
-
-    KeyedVector<size_t, CodecState> stateByTrack;
-
-    CodecState *vidState = NULL;
-    for (size_t i = 0; i < extractor->countTracks(); ++i) {
-        sp<AMessage> format;
-        status_t err = extractor->getTrackFormat(i, &format);
-        CHECK(err == OK);
-
-        AString mime;
-        CHECK(format->findString("mime", &mime));
-        bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
-        if (!isVideo) {
-            continue;
-        }
-
-        ALOGV("selecting track %zu", i);
-
-        err = extractor->selectTrack(i);
-        CHECK(err == OK);
-
-        CodecState *state =
-            &stateByTrack.editValueAt(stateByTrack.add(i, CodecState()));
-
-        vidState = state;
-
-        state->mNumBuffersDecoded = 0;
-
-        state->mCodec = MediaCodec::CreateByType(
-                looper, mime.c_str(), false /* encoder */);
-
-        CHECK(state->mCodec != NULL);
-
-        err = state->mCodec->configure(
-                format, NULL /* surface */, NULL /* crypto */, 0 /* flags */);
-
-        CHECK(err == OK);
-
-        state->mSignalledInputEOS = false;
-        state->mSawOutputEOS = false;
-
-        break;
-    }
-    CHECK(!stateByTrack.isEmpty());
-    CHECK(vidState != NULL);
-    sp<AMessage> vidFormat;
-    vidState->mCodec->getOutputFormat(&vidFormat);
-
-    // set filter to use ARGB8888
-    vidFormat->setInt32("color-format", OMX_COLOR_Format32bitARGB8888);
-    // set app cache directory path
-    vidFormat->setString("cacheDir", "/system/bin");
-
-    // create RenderScript context for RSFilters
-    RSC::sp<RSC::RS> context = new RSC::RS();
-    context->init("/system/bin");
-
-    sp<RenderScriptWrapper::RSFilterCallback> rsFilter;
-
-    // create renderscript wrapper for RSFilters
-    sp<RenderScriptWrapper> rsWrapper = new RenderScriptWrapper;
-    rsWrapper->mContext = context.get();
-
-    CodecState *filterState = new CodecState();
-    filterState->mNumBuffersDecoded = 0;
-
-    sp<AMessage> params = new AMessage();
-
-    switch (filterType) {
-        case FILTERTYPE_ZERO:
-        {
-            filterState->mCodec = MediaCodec::CreateByComponentName(
-                    looper, "android.filter.zerofilter");
-            params->setInt32("invert", kInvert);
-            break;
-        }
-        case FILTERTYPE_INTRINSIC_BLUR:
-        {
-            filterState->mCodec = MediaCodec::CreateByComponentName(
-                    looper, "android.filter.intrinsicblur");
-            params->setFloat("blur-radius", kBlurRadius);
-            break;
-        }
-        case FILTERTYPE_SATURATION:
-        {
-            filterState->mCodec = MediaCodec::CreateByComponentName(
-                    looper, "android.filter.saturation");
-            params->setFloat("saturation", kSaturation);
-            break;
-        }
-        case FILTERTYPE_RS_SATURATION:
-        {
-            SaturationRSFilter *satFilter = new SaturationRSFilter;
-            satFilter->init(context);
-            rsFilter = satFilter;
-            rsWrapper->mCallback = rsFilter;
-            vidFormat->setObject("rs-wrapper", rsWrapper);
-
-            filterState->mCodec = MediaCodec::CreateByComponentName(
-                    looper, "android.filter.RenderScript");
-            break;
-        }
-        case FILTERTYPE_RS_NIGHT_VISION:
-        {
-            NightVisionRSFilter *nightVisionFilter = new NightVisionRSFilter;
-            nightVisionFilter->init(context);
-            rsFilter = nightVisionFilter;
-            rsWrapper->mCallback = rsFilter;
-            vidFormat->setObject("rs-wrapper", rsWrapper);
-
-            filterState->mCodec = MediaCodec::CreateByComponentName(
-                    looper, "android.filter.RenderScript");
-            break;
-        }
-        case FILTERTYPE_RS_ARGB_TO_RGBA:
-        {
-            ARGBToRGBARSFilter *argbToRgbaFilter = new ARGBToRGBARSFilter;
-            argbToRgbaFilter->init(context);
-            rsFilter = argbToRgbaFilter;
-            rsWrapper->mCallback = rsFilter;
-            vidFormat->setObject("rs-wrapper", rsWrapper);
-
-            filterState->mCodec = MediaCodec::CreateByComponentName(
-                    looper, "android.filter.RenderScript");
-            break;
-        }
-        default:
-        {
-            LOG_ALWAYS_FATAL("mediacodec.cpp error: unrecognized FilterType");
-            break;
-        }
-    }
-    CHECK(filterState->mCodec != NULL);
-
-    status_t err = filterState->mCodec->configure(
-            vidFormat /* format */, surface, NULL /* crypto */, 0 /* flags */);
-    CHECK(err == OK);
-
-    filterState->mSignalledInputEOS = false;
-    filterState->mSawOutputEOS = false;
-
-    int64_t startTimeUs = android::ALooper::GetNowUs();
-    int64_t startTimeRender = -1;
-
-    for (size_t i = 0; i < stateByTrack.size(); ++i) {
-        CodecState *state = &stateByTrack.editValueAt(i);
-
-        sp<MediaCodec> codec = state->mCodec;
-
-        CHECK_EQ((status_t)OK, codec->start());
-
-        CHECK_EQ((status_t)OK, codec->getInputBuffers(&state->mInBuffers));
-        CHECK_EQ((status_t)OK, codec->getOutputBuffers(&state->mOutBuffers));
-
-        ALOGV("got %zu input and %zu output buffers",
-                state->mInBuffers.size(), state->mOutBuffers.size());
-    }
-
-    CHECK_EQ((status_t)OK, filterState->mCodec->setParameters(params));
-
-    if (kTestFlush) {
-        status_t flushErr = filterState->mCodec->flush();
-        if (flushErr == OK) {
-            ALOGE("FAIL: Flush before start returned OK");
-        } else {
-            ALOGV("Flush before start returned status %d, usually ENOSYS (-38)",
-                    flushErr);
-        }
-    }
-
-    CHECK_EQ((status_t)OK, filterState->mCodec->start());
-    CHECK_EQ((status_t)OK, filterState->mCodec->getInputBuffers(
-            &filterState->mInBuffers));
-    CHECK_EQ((status_t)OK, filterState->mCodec->getOutputBuffers(
-            &filterState->mOutBuffers));
-
-    if (kTestFlush) {
-        status_t flushErr = filterState->mCodec->flush();
-        if (flushErr != OK) {
-            ALOGE("FAIL: Flush after start returned %d, expect OK (0)",
-                    flushErr);
-        } else {
-            ALOGV("Flush immediately after start OK");
-        }
-    }
-
-    List<DecodedFrame> decodedFrameIndices;
-
-    // loop until decoder reaches EOS
-    bool sawInputEOS = false;
-    bool sawOutputEOSOnAllTracks = false;
-    while (!sawOutputEOSOnAllTracks) {
-        if (!sawInputEOS) {
-            size_t trackIndex;
-            status_t err = extractor->getSampleTrackIndex(&trackIndex);
-
-            if (err != OK) {
-                ALOGV("saw input eos");
-                sawInputEOS = true;
-            } else {
-                CodecState *state = &stateByTrack.editValueFor(trackIndex);
-
-                size_t index;
-                err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
-
-                if (err == OK) {
-                    ALOGV("filling input buffer %zu", index);
-
-                    const sp<MediaCodecBuffer> &buffer = state->mInBuffers.itemAt(index);
-                    sp<ABuffer> abuffer = new ABuffer(buffer->base(), buffer->capacity());
-
-                    err = extractor->readSampleData(abuffer);
-                    CHECK(err == OK);
-                    buffer->setRange(abuffer->offset(), abuffer->size());
-
-                    int64_t timeUs;
-                    err = extractor->getSampleTime(&timeUs);
-                    CHECK(err == OK);
-
-                    uint32_t bufferFlags = 0;
-
-                    err = state->mCodec->queueInputBuffer(
-                            index, 0 /* offset */, buffer->size(),
-                            timeUs, bufferFlags);
-
-                    CHECK(err == OK);
-
-                    extractor->advance();
-                } else {
-                    CHECK_EQ(err, -EAGAIN);
-                }
-            }
-        } else {
-            for (size_t i = 0; i < stateByTrack.size(); ++i) {
-                CodecState *state = &stateByTrack.editValueAt(i);
-
-                if (!state->mSignalledInputEOS) {
-                    size_t index;
-                    status_t err =
-                        state->mCodec->dequeueInputBuffer(&index, kTimeout);
-
-                    if (err == OK) {
-                        ALOGV("signalling input EOS on track %zu", i);
-
-                        err = state->mCodec->queueInputBuffer(
-                                index, 0 /* offset */, 0 /* size */,
-                                0ll /* timeUs */, MediaCodec::BUFFER_FLAG_EOS);
-
-                        CHECK(err == OK);
-
-                        state->mSignalledInputEOS = true;
-                    } else {
-                        CHECK_EQ(err, -EAGAIN);
-                    }
-                }
-            }
-        }
-
-        sawOutputEOSOnAllTracks = true;
-        for (size_t i = 0; i < stateByTrack.size(); ++i) {
-            CodecState *state = &stateByTrack.editValueAt(i);
-
-            if (state->mSawOutputEOS) {
-                continue;
-            } else {
-                sawOutputEOSOnAllTracks = false;
-            }
-
-            DecodedFrame frame;
-            status_t err = state->mCodec->dequeueOutputBuffer(
-                    &frame.index, &frame.offset, &frame.size,
-                    &frame.presentationTimeUs, &frame.flags, kTimeout);
-
-            if (err == OK) {
-                ALOGV("draining decoded buffer %zu, time = %lld us",
-                        frame.index, (long long)frame.presentationTimeUs);
-
-                ++(state->mNumBuffersDecoded);
-
-                decodedFrameIndices.push_back(frame);
-
-                if (frame.flags & MediaCodec::BUFFER_FLAG_EOS) {
-                    ALOGV("reached EOS on decoder output.");
-                    state->mSawOutputEOS = true;
-                }
-
-            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
-                ALOGV("INFO_OUTPUT_BUFFERS_CHANGED");
-                CHECK_EQ((status_t)OK, state->mCodec->getOutputBuffers(
-                        &state->mOutBuffers));
-
-                ALOGV("got %zu output buffers", state->mOutBuffers.size());
-            } else if (err == INFO_FORMAT_CHANGED) {
-                sp<AMessage> format;
-                CHECK_EQ((status_t)OK, state->mCodec->getOutputFormat(&format));
-
-                ALOGV("INFO_FORMAT_CHANGED: %s",
-                        format->debugString().c_str());
-            } else {
-                CHECK_EQ(err, -EAGAIN);
-            }
-
-            tryCopyDecodedBuffer(&decodedFrameIndices, filterState, vidState);
-
-            tryDrainOutputBuffer(
-                    filterState, surface, renderSurface,
-                    useTimestamp, &startTimeRender);
-        }
-    }
-
-    // after EOS on decoder, let filter reach EOS
-    while (!filterState->mSawOutputEOS) {
-        tryCopyDecodedBuffer(&decodedFrameIndices, filterState, vidState);
-
-        tryDrainOutputBuffer(
-                filterState, surface, renderSurface,
-                useTimestamp, &startTimeRender);
-    }
-
-    int64_t elapsedTimeUs = android::ALooper::GetNowUs() - startTimeUs;
-
-    for (size_t i = 0; i < stateByTrack.size(); ++i) {
-        CodecState *state = &stateByTrack.editValueAt(i);
-
-        CHECK_EQ((status_t)OK, state->mCodec->release());
-
-        printf("track %zu: %" PRId64 " frames decoded and filtered, "
-                "%.2f fps.\n", i, state->mNumBuffersDecoded,
-                state->mNumBuffersDecoded * 1E6 / elapsedTimeUs);
-    }
-
-    return 0;
-}
-
-}  // namespace android
-
-int main(int argc, char **argv) {
-    using namespace android;
-
-    const char *me = argv[0];
-
-    bool useSurface = false;
-    bool renderSurface = false;
-    bool useTimestamp = false;
-    FilterType filterType = FILTERTYPE_ZERO;
-
-    int res;
-    while ((res = getopt(argc, argv, "bcnrszTRSh")) >= 0) {
-        switch (res) {
-            case 'b':
-            {
-                filterType = FILTERTYPE_INTRINSIC_BLUR;
-                break;
-            }
-            case 'c':
-            {
-                filterType = FILTERTYPE_RS_ARGB_TO_RGBA;
-                break;
-            }
-            case 'n':
-            {
-                filterType = FILTERTYPE_RS_NIGHT_VISION;
-                break;
-            }
-            case 'r':
-            {
-                filterType = FILTERTYPE_RS_SATURATION;
-                break;
-            }
-            case 's':
-            {
-                filterType = FILTERTYPE_SATURATION;
-                break;
-            }
-            case 'z':
-            {
-                filterType = FILTERTYPE_ZERO;
-                break;
-            }
-            case 'T':
-            {
-                useTimestamp = true;
-                FALLTHROUGH_INTENDED;
-            }
-            case 'R':
-            {
-                renderSurface = true;
-                FALLTHROUGH_INTENDED;
-            }
-            case 'S':
-            {
-                useSurface = true;
-                break;
-            }
-            case '?':
-            case 'h':
-            default:
-            {
-                usage(me);
-                break;
-            }
-        }
-    }
-
-    argc -= optind;
-    argv += optind;
-
-    if (argc != 1) {
-        usage(me);
-    }
-
-    ProcessState::self()->startThreadPool();
-
-    android::sp<android::ALooper> looper = new android::ALooper;
-    looper->start();
-
-    android::sp<SurfaceComposerClient> composerClient;
-    android::sp<SurfaceControl> control;
-    android::sp<Surface> surface;
-
-    if (useSurface) {
-        composerClient = new SurfaceComposerClient;
-        CHECK_EQ((status_t)OK, composerClient->initCheck());
-
-        const android::sp<IBinder> display = SurfaceComposerClient::getInternalDisplayToken();
-        CHECK(display != nullptr);
-
-        ui::DisplayMode mode;
-        CHECK_EQ(SurfaceComposerClient::getActiveDisplayMode(display, &mode), NO_ERROR);
-
-        const ui::Size& resolution = mode.resolution;
-        const ssize_t displayWidth = resolution.getWidth();
-        const ssize_t displayHeight = resolution.getHeight();
-
-        ALOGV("display is %zd x %zd", displayWidth, displayHeight);
-
-        control = composerClient->createSurface(
-                String8("A Surface"), displayWidth, displayHeight,
-                PIXEL_FORMAT_RGBA_8888, 0);
-
-        CHECK(control != NULL);
-        CHECK(control->isValid());
-
-        SurfaceComposerClient::Transaction{}
-                .setLayer(control, INT_MAX)
-                .show(control)
-                .apply();
-
-        surface = control->getSurface();
-        CHECK(surface != NULL);
-    }
-
-    decode(looper, argv[0], surface, renderSurface, useTimestamp, filterType);
-
-    if (useSurface) {
-        composerClient->dispose();
-    }
-
-    looper->stop();
-
-    return 0;
-}
diff --git a/cmds/stagefright/muxer.cpp b/cmds/stagefright/muxer.cpp
index bc7e41e..185491f 100644
--- a/cmds/stagefright/muxer.cpp
+++ b/cmds/stagefright/muxer.cpp
@@ -78,10 +78,14 @@
     int fd = open(outputFileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
 
     if (fd < 0) {
-        ALOGE("couldn't open file");
-        return fd;
+        ALOGE("couldn't open output file %s", outputFileName);
+        return 1;
     }
-    sp<MediaMuxer> muxer = new MediaMuxer(fd, container);
+    sp<MediaMuxer> muxer = MediaMuxer::create(fd, container);
+    if (muxer == nullptr) {
+        fprintf(stderr, "unable to instantiate muxer for format %d\n", container);
+        return 1;
+    }
     close(fd);
 
     size_t trackCount = extractor->countTracks();
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index 5743ad6..87e8832 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -89,6 +89,9 @@
         if (err != OK) {
             return err;
         }
+        if (buffer == nullptr) {
+            return AMEDIA_ERROR_UNKNOWN;
+        }
 
         char x = (char)((double)rand() / RAND_MAX * 255);
         memset((*buffer)->data(), x, mSize);
diff --git a/drm/README.md b/drm/README.md
new file mode 100644
index 0000000..2681aac
--- /dev/null
+++ b/drm/README.md
@@ -0,0 +1,13 @@
+## AIDL error handling
+
+Starting in **Android U (14)**, `libmediadrm` (app-side) understands extra error
+details from **AIDL** DRM HALs passed through the binder exception message
+as a json string. The supported fields are:
+* `cdmError` (*int*)
+* `oemError` (*int*)
+* `context` (*int*)
+* `errorMessage` (*str*)
+
+The errors details will be reported to apps through the java interface
+`android.media.MediaDrmThrowable`. Please see the javadoc of `MediaDrmThrowable`
+for detailed definitions of each field above.
diff --git a/drm/TEST_MAPPING b/drm/TEST_MAPPING
index 3642898..b2d4d6e 100644
--- a/drm/TEST_MAPPING
+++ b/drm/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit-large": [
+  "presubmit": [
     // The following tests validate codec and drm path.
     {
       "name": "GtsMediaTestCases",
diff --git a/drm/drmserver/Android.bp b/drm/drmserver/Android.bp
index df3a6a2..ab25c65 100644
--- a/drm/drmserver/Android.bp
+++ b/drm/drmserver/Android.bp
@@ -63,3 +63,39 @@
 
     init_rc: ["drmserver.rc"],
 }
+
+cc_fuzz {
+    name: "drmserver_fuzzer",
+
+    defaults: [
+        "service_fuzzer_defaults",
+    ],
+
+    srcs: [
+        "fuzzer/DrmFuzzer.cpp",
+        "DrmManagerService.cpp",
+        "DrmManager.cpp",
+    ],
+
+    static_libs: [
+        "libmediautils",
+        "liblog",
+        "libdl",
+        "libdrmframeworkcommon",
+        "libselinux",
+        "libstagefright_foundation",
+    ],
+
+     shared_libs: [
+         "libmediametrics",
+     ],
+
+     fuzz_config: {
+         libfuzzer_options: [
+             "max_len=50000",
+         ],
+         cc: [
+             "android-drm-team@google.com",
+         ],
+     },
+}
\ No newline at end of file
diff --git a/drm/drmserver/DrmManagerService.h b/drm/drmserver/DrmManagerService.h
index f9b8bef..56201d9 100644
--- a/drm/drmserver/DrmManagerService.h
+++ b/drm/drmserver/DrmManagerService.h
@@ -141,6 +141,8 @@
 
     virtual status_t dump(int fd, const Vector<String16>& args);
 
+    friend class DrmManagerServiceFuzzer;
+
 private:
     sp<DrmManager> mDrmManager;
 };
diff --git a/drm/drmserver/fuzzer/DrmFuzzer.cpp b/drm/drmserver/fuzzer/DrmFuzzer.cpp
new file mode 100644
index 0000000..4b23679
--- /dev/null
+++ b/drm/drmserver/fuzzer/DrmFuzzer.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "DrmManagerService.h"
+
+namespace android {
+class DrmManagerServiceFuzzer {
+public:
+    DrmManagerServiceFuzzer() {}
+
+    void fuzz(const uint8_t* data, size_t size) {
+          auto drmService = new DrmManagerService();
+          fuzzService(drmService, FuzzedDataProvider(data, size));
+    }
+};
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    android::DrmManagerServiceFuzzer serviceFuzzer;
+    serviceFuzzer.fuzz(data, size);
+    return 0;
+}
\ No newline at end of file
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
index be2b546..6e55a16 100644
--- a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
+++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.bp
@@ -48,7 +48,6 @@
     srcs: ["src/FwdLockEngine.cpp"],
 
     shared_libs: [
-        "libandroidicu",
         "libutils",
         "liblog",
         "libdl",
diff --git a/drm/libmediadrm/Android.bp b/drm/libmediadrm/Android.bp
index 408d216..7d68c5b 100644
--- a/drm/libmediadrm/Android.bp
+++ b/drm/libmediadrm/Android.bp
@@ -35,6 +35,8 @@
         "CryptoHalAidl.cpp",
         "DrmUtils.cpp",
         "DrmHalListener.cpp",
+        "DrmStatus.cpp",
+        "DrmMetricsLogger.cpp",
     ],
 
     local_include_dirs: [
@@ -74,6 +76,7 @@
     static_libs: [
         "resourcemanager_aidl_interface-ndk",
         "libaidlcommonsupport",
+        "libjsoncpp",
     ],
 
     export_shared_lib_headers: [
diff --git a/drm/libmediadrm/CryptoHal.cpp b/drm/libmediadrm/CryptoHal.cpp
index f95d527..fc1780d 100644
--- a/drm/libmediadrm/CryptoHal.cpp
+++ b/drm/libmediadrm/CryptoHal.cpp
@@ -71,7 +71,7 @@
     mCryptoHalHidl->notifyResolution(width, height);
 }
 
-status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHal::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
     // This requires plugin to be created.
     if (mCryptoHalAidl->initCheck() == OK) return mCryptoHalAidl->setMediaDrmSession(sessionId);
     return mCryptoHalHidl->setMediaDrmSession(sessionId);
diff --git a/drm/libmediadrm/CryptoHalAidl.cpp b/drm/libmediadrm/CryptoHalAidl.cpp
index 8b9d1de..c1fd797 100644
--- a/drm/libmediadrm/CryptoHalAidl.cpp
+++ b/drm/libmediadrm/CryptoHalAidl.cpp
@@ -41,7 +41,7 @@
 using ::aidl::android::hardware::drm::DecryptArgs;
 
 using ::android::sp;
-using ::android::DrmUtils::statusAidlToStatusT;
+using ::android::DrmUtils::statusAidlToDrmStatus;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_memory;
@@ -260,7 +260,7 @@
     }
 }
 
-status_t CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalAidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -268,7 +268,7 @@
     }
 
     auto err = mPlugin->setMediaDrmSession(toStdVec(sessionId));
-    return statusAidlToStatusT(err);
+    return statusAidlToDrmStatus(err);
 }
 
 ssize_t CryptoHalAidl::decrypt(const uint8_t keyId[16], const uint8_t iv[16],
@@ -352,7 +352,7 @@
     int32_t result = 0;
     ::ndk::ScopedAStatus statusAidl = mPlugin->decrypt(args, &result);
 
-    err = statusAidlToStatusT(statusAidl);
+    err = statusAidlToDrmStatus(statusAidl);
     std::string msgStr(statusAidl.getMessage());
     if (errorDetailMsg != nullptr) {
         *errorDetailMsg = toString8(msgStr);
diff --git a/drm/libmediadrm/CryptoHalHidl.cpp b/drm/libmediadrm/CryptoHalHidl.cpp
index 55364b5..458a1ae 100644
--- a/drm/libmediadrm/CryptoHalHidl.cpp
+++ b/drm/libmediadrm/CryptoHalHidl.cpp
@@ -386,7 +386,7 @@
     ALOGE_IF(!hResult.isOk(), "notifyResolution txn failed %s", hResult.description().c_str());
 }
 
-status_t CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
+DrmStatus CryptoHalHidl::setMediaDrmSession(const Vector<uint8_t>& sessionId) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index c394d5a..754f066 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -20,6 +20,7 @@
 #include <mediadrm/DrmHal.h>
 #include <mediadrm/DrmHalAidl.h>
 #include <mediadrm/DrmHalHidl.h>
+#include <mediadrm/DrmStatus.h>
 #include <mediadrm/DrmUtils.h>
 
 namespace android {
@@ -31,49 +32,49 @@
 
 DrmHal::~DrmHal() {}
 
-status_t DrmHal::initCheck() const {
-    if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return OK;
-    if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT) return NO_INIT;
+DrmStatus DrmHal::initCheck() const {
+    if (mDrmHalAidl->initCheck() == OK || mDrmHalHidl->initCheck() == OK) return DrmStatus(OK);
+    if (mDrmHalAidl->initCheck() == NO_INIT || mDrmHalHidl->initCheck() == NO_INIT)
+        return DrmStatus(NO_INIT);
     return mDrmHalHidl->initCheck();
 }
 
-status_t DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
-                                         DrmPlugin::SecurityLevel securityLevel, bool* result) {
-    status_t statusResult;
-    statusResult = mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+DrmStatus DrmHal::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                          DrmPlugin::SecurityLevel securityLevel, bool* result) {
+    DrmStatus statusResult =
+            mDrmHalAidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
     if (*result) return statusResult;
     return mDrmHalHidl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
 }
 
-status_t DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
-    status_t statusResult;
-    statusResult = mDrmHalAidl->createPlugin(uuid, appPackageName);
-    if (statusResult != OK) return mDrmHalHidl->createPlugin(uuid, appPackageName);
-    return statusResult;
+DrmStatus DrmHal::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+    return mDrmHalAidl->createPlugin(uuid, appPackageName) == OK
+                   ? DrmStatus(OK)
+                   : mDrmHalHidl->createPlugin(uuid, appPackageName);
 }
 
-status_t DrmHal::destroyPlugin() {
-    status_t statusResult = mDrmHalAidl->destroyPlugin();
-    status_t statusResultHidl = mDrmHalHidl->destroyPlugin();
+DrmStatus DrmHal::destroyPlugin() {
+    DrmStatus statusResult = mDrmHalAidl->destroyPlugin();
+    DrmStatus statusResultHidl = mDrmHalHidl->destroyPlugin();
     if (statusResult != OK) return statusResult;
     return statusResultHidl;
 }
 
-status_t DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHal::openSession(DrmPlugin::SecurityLevel securityLevel, Vector<uint8_t>& sessionId) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->openSession(securityLevel, sessionId);
     return mDrmHalHidl->openSession(securityLevel, sessionId);
 }
 
-status_t DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHal::closeSession(Vector<uint8_t> const& sessionId) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->closeSession(sessionId);
     return mDrmHalHidl->closeSession(sessionId);
 }
 
-status_t DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
-                               String8 const& mimeType, DrmPlugin::KeyType keyType,
-                               KeyedVector<String8, String8> const& optionalParameters,
-                               Vector<uint8_t>& request, String8& defaultUrl,
-                               DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHal::getKeyRequest(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& initData,
+                                String8 const& mimeType, DrmPlugin::KeyType keyType,
+                                KeyedVector<String8, String8> const& optionalParameters,
+                                Vector<uint8_t>& request, String8& defaultUrl,
+                                DrmPlugin::KeyRequestType* keyRequestType) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->getKeyRequest(sessionId, initData, mimeType, keyType,
                                           optionalParameters, request, defaultUrl, keyRequestType);
@@ -81,212 +82,212 @@
                                       request, defaultUrl, keyRequestType);
 }
 
-status_t DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
-                                    Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
+DrmStatus DrmHal::provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                     Vector<uint8_t> const& response, Vector<uint8_t>& keySetId) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->provideKeyResponse(sessionId, response, keySetId);
     return mDrmHalHidl->provideKeyResponse(sessionId, response, keySetId);
 }
 
-status_t DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::removeKeys(Vector<uint8_t> const& keySetId) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeKeys(keySetId);
     return mDrmHalHidl->removeKeys(keySetId);
 }
 
-status_t DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->restoreKeys(sessionId, keySetId);
     return mDrmHalHidl->restoreKeys(sessionId, keySetId);
 }
 
-status_t DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
-                                KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHal::queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                 KeyedVector<String8, String8>& infoMap) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->queryKeyStatus(sessionId, infoMap);
     return mDrmHalHidl->queryKeyStatus(sessionId, infoMap);
 }
 
-status_t DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
-                                     Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHal::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+                                      Vector<uint8_t>& request, String8& defaultUrl) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
     return mDrmHalHidl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
 }
 
-status_t DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
-                                          Vector<uint8_t>& certificate,
-                                          Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHal::provideProvisionResponse(Vector<uint8_t> const& response,
+                                           Vector<uint8_t>& certificate,
+                                           Vector<uint8_t>& wrappedKey) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->provideProvisionResponse(response, certificate, wrappedKey);
     return mDrmHalHidl->provideProvisionResponse(response, certificate, wrappedKey);
 }
 
-status_t DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHal::getSecureStops(List<Vector<uint8_t>>& secureStops) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStops(secureStops);
     return mDrmHalHidl->getSecureStops(secureStops);
 }
 
-status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHal::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStopIds(secureStopIds);
     return mDrmHalHidl->getSecureStopIds(secureStopIds);
 }
 
-status_t DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHal::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecureStop(ssid, secureStop);
     return mDrmHalHidl->getSecureStop(ssid, secureStop);
 }
 
-status_t DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHal::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->releaseSecureStops(ssRelease);
     return mDrmHalHidl->releaseSecureStops(ssRelease);
 }
 
-status_t DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHal::removeSecureStop(Vector<uint8_t> const& ssid) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeSecureStop(ssid);
     return mDrmHalHidl->removeSecureStop(ssid);
 }
 
-status_t DrmHal::removeAllSecureStops() {
+DrmStatus DrmHal::removeAllSecureStops() {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeAllSecureStops();
     return mDrmHalHidl->removeAllSecureStops();
 }
 
-status_t DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
-                               DrmPlugin::HdcpLevel* maxLevel) const {
+DrmStatus DrmHal::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+                                DrmPlugin::HdcpLevel* maxLevel) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getHdcpLevels(connectedLevel, maxLevel);
     return mDrmHalHidl->getHdcpLevels(connectedLevel, maxLevel);
 }
 
-status_t DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
+DrmStatus DrmHal::getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->getNumberOfSessions(currentSessions, maxSessions);
     return mDrmHalHidl->getNumberOfSessions(currentSessions, maxSessions);
 }
 
-status_t DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
-                                  DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHal::getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                   DrmPlugin::SecurityLevel* level) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getSecurityLevel(sessionId, level);
     return mDrmHalHidl->getSecurityLevel(sessionId, level);
 }
 
-status_t DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHal::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getOfflineLicenseKeySetIds(keySetIds);
     return mDrmHalHidl->getOfflineLicenseKeySetIds(keySetIds);
 }
 
-status_t DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHal::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->removeOfflineLicense(keySetId);
     return mDrmHalHidl->removeOfflineLicense(keySetId);
 }
 
-status_t DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
-                                        DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHal::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+                                         DrmPlugin::OfflineLicenseState* licenseState) const {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->getOfflineLicenseState(keySetId, licenseState);
     return mDrmHalHidl->getOfflineLicenseState(keySetId, licenseState);
 }
 
-status_t DrmHal::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHal::getPropertyString(String8 const& name, String8& value) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyString(name, value);
     return mDrmHalHidl->getPropertyString(name, value);
 }
 
-status_t DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHal::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getPropertyByteArray(name, value);
     return mDrmHalHidl->getPropertyByteArray(name, value);
 }
 
-status_t DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHal::setPropertyString(String8 const& name, String8 const& value) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyString(name, value);
     return mDrmHalHidl->setPropertyString(name, value);
 }
 
-status_t DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHal::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPropertyByteArray(name, value);
     return mDrmHalHidl->setPropertyByteArray(name, value);
 }
 
-status_t DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHal::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getMetrics(consumer);
     return mDrmHalHidl->getMetrics(consumer);
 }
 
-status_t DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHal::setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->setCipherAlgorithm(sessionId, algorithm);
     return mDrmHalHidl->setCipherAlgorithm(sessionId, algorithm);
 }
 
-status_t DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHal::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setMacAlgorithm(sessionId, algorithm);
     return mDrmHalHidl->setMacAlgorithm(sessionId, algorithm);
 }
 
-status_t DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                         Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                         Vector<uint8_t>& output) {
+DrmStatus DrmHal::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                          Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                          Vector<uint8_t>& output) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->encrypt(sessionId, keyId, input, iv, output);
     return mDrmHalHidl->encrypt(sessionId, keyId, input, iv, output);
 }
 
-status_t DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                         Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                         Vector<uint8_t>& output) {
+DrmStatus DrmHal::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                          Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                          Vector<uint8_t>& output) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->decrypt(sessionId, keyId, input, iv, output);
     return mDrmHalHidl->decrypt(sessionId, keyId, input, iv, output);
 }
 
-status_t DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                      Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHal::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                       Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->sign(sessionId, keyId, message, signature);
     return mDrmHalHidl->sign(sessionId, keyId, message, signature);
 }
 
-status_t DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                        Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
-                        bool& match) {
+DrmStatus DrmHal::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                         Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                         bool& match) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->verify(sessionId, keyId, message, signature, match);
     return mDrmHalHidl->verify(sessionId, keyId, message, signature, match);
 }
 
-status_t DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
-                         Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
-                         Vector<uint8_t>& signature) {
+DrmStatus DrmHal::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                          Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+                          Vector<uint8_t>& signature) {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
     return mDrmHalHidl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
 }
 
-status_t DrmHal::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHal::setListener(const sp<IDrmClient>& listener) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setListener(listener);
     return mDrmHalHidl->setListener(listener);
 }
 
-status_t DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHal::requiresSecureDecoder(const char* mime, bool* required) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->requiresSecureDecoder(mime, required);
     return mDrmHalHidl->requiresSecureDecoder(mime, required);
 }
 
-status_t DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
-                                       bool* required) const {
+DrmStatus DrmHal::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
+                                        bool* required) const {
     if (mDrmHalAidl->initCheck() == OK)
         return mDrmHalAidl->requiresSecureDecoder(mime, securityLevel, required);
     return mDrmHalHidl->requiresSecureDecoder(mime, securityLevel, required);
 }
 
-status_t DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHal::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->setPlaybackId(sessionId, playbackId);
     return mDrmHalHidl->setPlaybackId(sessionId, playbackId);
 }
 
-status_t DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHal::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
     if (mDrmHalAidl->initCheck() == OK) return mDrmHalAidl->getLogMessages(logs);
     return mDrmHalHidl->getLogMessages(logs);
 }
 
-status_t DrmHal::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHal::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
     status_t statusResult;
     statusResult = mDrmHalAidl->getSupportedSchemes(schemes);
     if (statusResult == OK) return statusResult;
diff --git a/drm/libmediadrm/DrmHalAidl.cpp b/drm/libmediadrm/DrmHalAidl.cpp
index bdd83e9..5ec7337 100644
--- a/drm/libmediadrm/DrmHalAidl.cpp
+++ b/drm/libmediadrm/DrmHalAidl.cpp
@@ -29,9 +29,9 @@
 #include <media/stagefright/foundation/hexdump.h>
 #include <mediadrm/DrmHalAidl.h>
 #include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
 #include <mediadrm/DrmUtils.h>
 
-using ::android::DrmUtils::statusAidlToStatusT;
 using ::aidl::android::hardware::drm::CryptoSchemes;
 using ::aidl::android::hardware::drm::DrmMetricNamedValue;
 using ::aidl::android::hardware::drm::DrmMetricValue;
@@ -55,6 +55,7 @@
 using ::aidl::android::hardware::drm::Status;
 using ::aidl::android::hardware::drm::SupportedContentType;
 using ::aidl::android::hardware::drm::Uuid;
+using ::android::DrmUtils::statusAidlToDrmStatus;
 using DrmMetricGroupAidl = ::aidl::android::hardware::drm::DrmMetricGroup;
 using DrmMetricGroupHidl = ::android::hardware::drm::V1_1::DrmMetricGroup;
 using DrmMetricAidl = ::aidl::android::hardware::drm::DrmMetric;
@@ -392,23 +393,24 @@
 
 // DrmHalAidl methods
 DrmHalAidl::DrmHalAidl()
-    : mListener(::ndk::SharedRefBase::make<DrmHalListener>(&mMetrics)),
+    : mMetrics(std::make_shared<MediaDrmMetrics>()),
+      mListener(::ndk::SharedRefBase::make<DrmHalListener>(mMetrics)),
       mFactories(DrmUtils::makeDrmFactoriesAidl()),
       mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {}
 
-status_t DrmHalAidl::initCheck() const {
-    return mInitCheck;
+DrmStatus DrmHalAidl::initCheck() const {
+    return DrmStatus(mInitCheck);
 }
 
 DrmHalAidl::~DrmHalAidl() {}
 
-status_t DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHalAidl::setListener(const sp<IDrmClient>& listener) {
     mListener->setListener(listener);
-    return NO_ERROR;
+    return DrmStatus(NO_ERROR);
 }
 
-status_t DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
-                                             DrmPlugin::SecurityLevel level, bool* isSupported) {
+DrmStatus DrmHalAidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel level, bool* isSupported) {
     Mutex::Autolock autoLock(mLock);
     *isSupported = false;
     Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
@@ -438,9 +440,9 @@
                 // isCryptoSchemeSupported(uuid, mimeType)
                 *isSupported = contentTypes.count(mimeTypeStr);
             }
-            return OK;
+            return DrmStatus(OK);
         } else if (mimeType == "") {
-            return BAD_VALUE;
+            return DrmStatus(BAD_VALUE);
         }
 
         auto ct = contentTypes[mimeTypeStr];
@@ -452,17 +454,17 @@
         break;
     }
 
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+DrmStatus DrmHalAidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
     Mutex::Autolock autoLock(mLock);
-
+    if (mInitCheck == ERROR_UNSUPPORTED) return mInitCheck;
     Uuid uuidAidl = DrmUtils::toAidlUuid(uuid);
     std::string appPackageNameAidl = toStdString(appPackageName);
     std::shared_ptr<IDrmPluginAidl> pluginAidl;
-    mMetrics.SetAppPackageName(appPackageName);
-    mMetrics.SetAppUid(AIBinder_getCallingUid());
+    mMetrics->SetAppPackageName(appPackageName);
+    mMetrics->SetAppUid(AIBinder_getCallingUid());
     for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
         ::ndk::ScopedAStatus status =
                 mFactories[i]->createDrmPlugin(uuidAidl, appPackageNameAidl, &pluginAidl);
@@ -497,10 +499,10 @@
         }
     }
 
-    return mInitCheck;
+    return DrmStatus(mInitCheck);
 }
 
-status_t DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHalAidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -510,14 +512,14 @@
         return ERROR_DRM_CANNOT_HANDLE;
     }
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
     bool retry = true;
     do {
         std::vector<uint8_t> aSessionId;
 
         ::ndk::ScopedAStatus status = mPlugin->openSession(aSecurityLevel, &aSessionId);
         if (status.isOk()) sessionId = toVector(aSessionId);
-        err = statusAidlToStatusT(status);
+        err = statusAidlToDrmStatus(status);
 
         if (err == ERROR_DRM_RESOURCE_BUSY && retry) {
             mLock.unlock();
@@ -538,20 +540,20 @@
                 AIBinder_getCallingPid(), std::static_pointer_cast<IResourceManagerClient>(client),
                 sessionId);
         mOpenSessions.push_back(client);
-        mMetrics.SetSessionStart(sessionId);
+        mMetrics->SetSessionStart(sessionId);
     }
 
-    mMetrics.mOpenSessionCounter.Increment(err);
+    mMetrics->mOpenSessionCounter.Increment(err);
     return err;
 }
 
-status_t DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHalAidl::closeSession(Vector<uint8_t> const& sessionId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
     ::ndk::ScopedAStatus status = mPlugin->closeSession(sessionIdAidl);
-    status_t response = statusAidlToStatusT(status);
+    DrmStatus response = statusAidlToDrmStatus(status);
     if (status.isOk()) {
         DrmSessionManager::Instance()->removeSession(sessionId);
         for (auto i = mOpenSessions.begin(); i != mOpenSessions.end(); i++) {
@@ -561,22 +563,22 @@
             }
         }
 
-        mMetrics.SetSessionEnd(sessionId);
+        mMetrics->SetSessionEnd(sessionId);
     }
 
-    mMetrics.mCloseSessionCounter.Increment(response);
+    mMetrics->mCloseSessionCounter.Increment(response);
     return response;
 }
 
-status_t DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
-                                   Vector<uint8_t> const& initData, String8 const& mimeType,
-                                   DrmPlugin::KeyType keyType,
-                                   KeyedVector<String8, String8> const& optionalParameters,
-                                   Vector<uint8_t>& request, String8& defaultUrl,
-                                   DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHalAidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+                                    Vector<uint8_t> const& initData, String8 const& mimeType,
+                                    DrmPlugin::KeyType keyType,
+                                    KeyedVector<String8, String8> const& optionalParameters,
+                                    Vector<uint8_t>& request, String8& defaultUrl,
+                                    DrmPlugin::KeyRequestType* keyRequestType) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
-    EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
+    EventTimer<status_t> keyRequestTimer(&mMetrics->mGetKeyRequestTimeUs);
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
@@ -592,7 +594,7 @@
         return BAD_VALUE;
     }
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
     std::vector<uint8_t> initDataAidl = toStdVec(initData);
@@ -607,21 +609,21 @@
         *keyRequestType = toKeyRequestType(keyRequest.requestType);
     }
 
-    err = statusAidlToStatusT(status);
+    err = statusAidlToDrmStatus(status);
     keyRequestTimer.SetAttribute(err);
     return err;
 }
 
-status_t DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
-                                        Vector<uint8_t> const& response,
-                                        Vector<uint8_t>& keySetId) {
+DrmStatus DrmHalAidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                         Vector<uint8_t> const& response,
+                                         Vector<uint8_t>& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
-    EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
+    EventTimer<status_t> keyResponseTimer(&mMetrics->mProvideKeyResponseTimeUs);
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     std::vector<uint8_t> sessionIdAidl = toStdVec(sessionId);
     std::vector<uint8_t> responseAidl = toStdVec(response);
@@ -630,21 +632,21 @@
             mPlugin->provideKeyResponse(sessionIdAidl, responseAidl, &keySetIdsAidl);
 
     if (status.isOk()) keySetId = toVector(keySetIdsAidl.keySetId);
-    err = statusAidlToStatusT(status);
+    err = statusAidlToDrmStatus(status);
     keyResponseTimer.SetAttribute(err);
     return err;
 }
 
-status_t DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::removeKeys(Vector<uint8_t> const& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     ::ndk::ScopedAStatus status = mPlugin->removeKeys(toStdVec(keySetId));
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
-                                 Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::restoreKeys(Vector<uint8_t> const& sessionId,
+                                  Vector<uint8_t> const& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -653,11 +655,11 @@
     KeySetId keySetIdsAidl;
     keySetIdsAidl.keySetId = toStdVec(keySetId);
     ::ndk::ScopedAStatus status = mPlugin->restoreKeys(toStdVec(sessionId), keySetIdsAidl);
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
-                                    KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHalAidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                     KeyedVector<String8, String8>& infoMap) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -668,15 +670,15 @@
 
     infoMap = toKeyedVector(infoMapAidl);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
-                                         Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHalAidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+                                          Vector<uint8_t>& request, String8& defaultUrl) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     ProvisionRequest requestAidl;
     ::ndk::ScopedAStatus status = mPlugin->getProvisionRequest(
@@ -685,29 +687,29 @@
     request = toVector(requestAidl.request);
     defaultUrl = toString8(requestAidl.defaultUrl);
 
-    err = statusAidlToStatusT(status);
-    mMetrics.mGetProvisionRequestCounter.Increment(err);
+    err = statusAidlToDrmStatus(status);
+    mMetrics->mGetProvisionRequestCounter.Increment(err);
     return err;
 }
 
-status_t DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
-                                              Vector<uint8_t>& certificate,
-                                              Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHalAidl::provideProvisionResponse(Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& certificate,
+                                               Vector<uint8_t>& wrappedKey) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
     ProvideProvisionResponseResult result;
     ::ndk::ScopedAStatus status = mPlugin->provideProvisionResponse(toStdVec(response), &result);
 
     certificate = toVector(result.certificate);
     wrappedKey = toVector(result.wrappedKey);
-    err = statusAidlToStatusT(status);
-    mMetrics.mProvideProvisionResponseCounter.Increment(err);
+    err = statusAidlToDrmStatus(status);
+    mMetrics->mProvideProvisionResponseCounter.Increment(err);
     return err;
 }
 
-status_t DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHalAidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -716,10 +718,10 @@
 
     secureStops = toSecureStops(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHalAidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -728,10 +730,10 @@
 
     secureStopIds = toSecureStopIds(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHalAidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -743,10 +745,10 @@
 
     secureStop = toVector(result.opaqueData);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHalAidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -754,10 +756,10 @@
     ssId.opaqueData = toStdVec(ssRelease);
     ::ndk::ScopedAStatus status = mPlugin->releaseSecureStops(ssId);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHalAidl::removeSecureStop(Vector<uint8_t> const& ssid) {
     Mutex::Autolock autoLock(mLock);
 
     INIT_CHECK();
@@ -765,19 +767,19 @@
     SecureStopId ssidAidl;
     ssidAidl.secureStopId = toStdVec(ssid);
     ::ndk::ScopedAStatus status = mPlugin->removeSecureStop(ssidAidl);
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::removeAllSecureStops() {
+DrmStatus DrmHalAidl::removeAllSecureStops() {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     ::ndk::ScopedAStatus status = mPlugin->releaseAllSecureStops();
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
-                                   DrmPlugin::HdcpLevel* max) const {
+DrmStatus DrmHalAidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+                                    DrmPlugin::HdcpLevel* max) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -794,10 +796,10 @@
     *connected = toHdcpLevel(lvlsAidl.connectedLevel);
     *max = toHdcpLevel(lvlsAidl.maxLevel);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+DrmStatus DrmHalAidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -814,11 +816,11 @@
     *open = result.currentSessions;
     *max = result.maxSessions;
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
-                                      DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHalAidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                       DrmPlugin::SecurityLevel* level) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -833,10 +835,10 @@
 
     *level = toSecurityLevel(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHalAidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -845,21 +847,21 @@
 
     keySetIds = toKeySetIds(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalAidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     KeySetId keySetIdAidl;
     keySetIdAidl.keySetId = toStdVec(keySetId);
     ::ndk::ScopedAStatus status = mPlugin->removeOfflineLicense(keySetIdAidl);
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
-                                            DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHalAidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+                                             DrmPlugin::OfflineLicenseState* licenseState) const {
     Mutex::Autolock autoLock(mLock);
 
     INIT_CHECK();
@@ -873,15 +875,15 @@
 
     *licenseState = toOfflineLicenseState(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHalAidl::getPropertyString(String8 const& name, String8& value) const {
     Mutex::Autolock autoLock(mLock);
-    return getPropertyStringInternal(name, value);
+    return DrmStatus(getPropertyStringInternal(name, value));
 }
 
-status_t DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+DrmStatus DrmHalAidl::getPropertyStringInternal(String8 const& name, String8& value) const {
     // This function is internal to the class and should only be called while
     // mLock is already held.
     INIT_CHECK();
@@ -891,54 +893,55 @@
 
     value = toString8(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHalAidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
     Mutex::Autolock autoLock(mLock);
-    return getPropertyByteArrayInternal(name, value);
+    return DrmStatus(getPropertyByteArrayInternal(name, value));
 }
 
-status_t DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
-                                                  Vector<uint8_t>& value) const {
+DrmStatus DrmHalAidl::getPropertyByteArrayInternal(String8 const& name,
+                                                   Vector<uint8_t>& value) const {
     // This function is internal to the class and should only be called while
     // mLock is already held.
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     std::vector<uint8_t> result;
     ::ndk::ScopedAStatus status = mPlugin->getPropertyByteArray(toStdString(name), &result);
 
     value = toVector(result);
-    err = statusAidlToStatusT(status);
+    err = statusAidlToDrmStatus(status);
     if (name == kPropertyDeviceUniqueId) {
-        mMetrics.mGetDeviceUniqueIdCounter.Increment(err);
+        mMetrics->mGetDeviceUniqueIdCounter.Increment(err);
     }
     return err;
 }
 
-status_t DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHalAidl::setPropertyString(String8 const& name, String8 const& value) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     ::ndk::ScopedAStatus status = mPlugin->setPropertyString(toStdString(name), toStdString(value));
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHalAidl::setPropertyByteArray(String8 const& name,
+                                           Vector<uint8_t> const& value) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     ::ndk::ScopedAStatus status = mPlugin->setPropertyByteArray(toStdString(name), toStdVec(value));
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHalAidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
     if (consumer == nullptr) {
-        return UNEXPECTED_NULL;
+        return DrmStatus(UNEXPECTED_NULL);
     }
-    consumer->consumeFrameworkMetrics(mMetrics);
+    consumer->consumeFrameworkMetrics(*mMetrics.get());
 
     // Append vendor metrics if they are supported.
 
@@ -957,7 +960,7 @@
     vendor += description;
 
     hidl_vec<DrmMetricGroupHidl> pluginMetrics;
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     std::vector<DrmMetricGroupAidl> result;
     ::ndk::ScopedAStatus status = mPlugin->getMetrics(&result);
@@ -967,13 +970,13 @@
         consumer->consumeHidlMetrics(vendor, pluginMetrics);
     }
 
-    err = statusAidlToStatusT(status);
+    err = statusAidlToDrmStatus(status);
 
     return err;
 }
 
-status_t DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
-                                        String8 const& algorithm) {
+DrmStatus DrmHalAidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                         String8 const& algorithm) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -981,10 +984,10 @@
 
     ::ndk::ScopedAStatus status =
             mPlugin->setCipherAlgorithm(toStdVec(sessionId), toStdString(algorithm));
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHalAidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -992,12 +995,12 @@
 
     ::ndk::ScopedAStatus status =
             mPlugin->setMacAlgorithm(toStdVec(sessionId), toStdString(algorithm));
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                             Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                             Vector<uint8_t>& output) {
+DrmStatus DrmHalAidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1009,12 +1012,12 @@
 
     output = toVector(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                             Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                             Vector<uint8_t>& output) {
+DrmStatus DrmHalAidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1026,11 +1029,11 @@
 
     output = toVector(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                          Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHalAidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                           Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1042,12 +1045,12 @@
 
     signature = toVector(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                            Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
-                            bool& match) {
+DrmStatus DrmHalAidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                             Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                             bool& match) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1056,12 +1059,12 @@
     ::ndk::ScopedAStatus status = mPlugin->verify(toStdVec(sessionId), toStdVec(keyId),
                                                   toStdVec(message), toStdVec(signature), &match);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
-                             Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
-                             Vector<uint8_t>& signature) {
+DrmStatus DrmHalAidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                              Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+                              Vector<uint8_t>& signature) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1074,10 +1077,10 @@
 
     signature = toVector(result);
 
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime, bool* required) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1086,14 +1089,15 @@
         mPlugin->requiresSecureDecoder(mimeAidl, SecurityLevel::DEFAULT, required);
     if (!status.isOk()) {
         DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
-        return DEAD_OBJECT;
+        return DrmStatus(DEAD_OBJECT);
     }
 
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalAidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
-                                           bool* required) const {
+DrmStatus DrmHalAidl::requiresSecureDecoder(const char* mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool* required) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1101,7 +1105,7 @@
     std::string mimeAidl(mime);
     ::ndk::ScopedAStatus status = mPlugin->requiresSecureDecoder(mimeAidl, aLevel, required);
 
-    status_t err = statusAidlToStatusT(status);
+    DrmStatus err = statusAidlToDrmStatus(status);
     if (!status.isOk()) {
         DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %d", status.getServiceSpecificError());
     }
@@ -1109,17 +1113,17 @@
     return err;
 }
 
-status_t DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHalAidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
     std::string playbackIdAidl(playbackId);
     ::ndk::ScopedAStatus status = mPlugin->setPlaybackId(toStdVec(sessionId), playbackIdAidl);
-    return statusAidlToStatusT(status);
+    return statusAidlToDrmStatus(status);
 }
 
-status_t DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHalAidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
     Mutex::Autolock autoLock(mLock);
-    return DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs);
+    return DrmStatus(DrmUtils::GetLogMessagesAidl<IDrmPluginAidl>(mPlugin, logs));
 }
 
 void DrmHalAidl::closeOpenSessions() {
@@ -1143,7 +1147,7 @@
         getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
         metricsString = toBase64StringNoPad(metricsVector.array(), metricsVector.size());
         status_t res = android::reportDrmPluginMetrics(metricsString, vendor, description,
-                                                       mMetrics.GetAppUid());
+                                                       mMetrics->GetAppUid());
         if (res != OK) {
             ALOGE("Metrics were retrieved but could not be reported: %d", res);
         }
@@ -1153,7 +1157,7 @@
 
 std::string DrmHalAidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
     mediametrics_handle_t item(mediametrics_create("mediadrm"));
-    mediametrics_setUid(item, mMetrics.GetAppUid());
+    mediametrics_setUid(item, mMetrics->GetAppUid());
     String8 vendor;
     String8 description;
     status_t result = getPropertyStringInternal(String8("vendor"), vendor);
@@ -1170,7 +1174,7 @@
     }
 
     std::string serializedMetrics;
-    result = mMetrics.GetSerializedMetrics(&serializedMetrics);
+    result = mMetrics->GetSerializedMetrics(&serializedMetrics);
     if (result != OK) {
         ALOGE("Failed to serialize framework metrics: %d", result);
     }
@@ -1189,7 +1193,7 @@
     return serializedMetrics;
 }
 
-status_t DrmHalAidl::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHalAidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
     Mutex::Autolock autoLock(mLock);
 
     if (mFactories.empty()) return UNKNOWN_ERROR;
@@ -1205,14 +1209,14 @@
         }
     }
 
-    return OK;
+    return DrmStatus(OK);
 }
 
 void DrmHalAidl::cleanup() {
     closeOpenSessions();
 
     Mutex::Autolock autoLock(mLock);
-    reportFrameworkMetrics(reportPluginMetrics());
+    if (mInitCheck == OK) reportFrameworkMetrics(reportPluginMetrics());
 
     setListener(NULL);
     mInitCheck = NO_INIT;
@@ -1225,9 +1229,9 @@
     mPlugin.reset();
 }
 
-status_t DrmHalAidl::destroyPlugin() {
+DrmStatus DrmHalAidl::destroyPlugin() {
     cleanup();
-    return OK;
+    return DrmStatus(OK);
 }
 
 ::ndk::ScopedAStatus DrmHalAidl::onEvent(EventTypeAidl eventTypeAidl,
diff --git a/drm/libmediadrm/DrmHalHidl.cpp b/drm/libmediadrm/DrmHalHidl.cpp
index ea99483..6106aa7 100644
--- a/drm/libmediadrm/DrmHalHidl.cpp
+++ b/drm/libmediadrm/DrmHalHidl.cpp
@@ -35,6 +35,7 @@
 #include <mediadrm/DrmHalHidl.h>
 #include <mediadrm/DrmSessionClientInterface.h>
 #include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
 #include <mediadrm/DrmUtils.h>
 #include <mediadrm/IDrmMetricsConsumer.h>
 #include <utils/Log.h>
@@ -368,14 +369,14 @@
     return plugin;
 }
 
-status_t DrmHalHidl::initCheck() const {
-    return mInitCheck;
+DrmStatus DrmHalHidl::initCheck() const {
+    return DrmStatus(mInitCheck);
 }
 
-status_t DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
+DrmStatus DrmHalHidl::setListener(const sp<IDrmClient>& listener) {
     Mutex::Autolock lock(mEventLock);
     mListener = listener;
-    return NO_ERROR;
+    return DrmStatus(NO_ERROR);
 }
 
 Return<void> DrmHalHidl::sendEvent(EventType hEventType, const hidl_vec<uint8_t>& sessionId,
@@ -502,10 +503,10 @@
     return Void();
 }
 
-status_t DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
-                                                   const uint8_t uuid[16], const String8& mimeType,
-                                                   DrmPlugin::SecurityLevel level,
-                                                   bool* isSupported) {
+DrmStatus DrmHalHidl::matchMimeTypeAndSecurityLevel(const sp<IDrmFactory>& factory,
+                                                    const uint8_t uuid[16], const String8& mimeType,
+                                                    DrmPlugin::SecurityLevel level,
+                                                    bool* isSupported) {
     *isSupported = false;
 
     // handle default value cases
@@ -513,35 +514,35 @@
         if (mimeType == "") {
             // isCryptoSchemeSupported(uuid)
             *isSupported = true;
-            return OK;
+            return DrmStatus(OK);
         }
         // isCryptoSchemeSupported(uuid, mimeType)
         auto hResult = factory->isContentTypeSupported(mimeType.string());
         if (!hResult.isOk()) {
-            return DEAD_OBJECT;
+            return DrmStatus(DEAD_OBJECT);
         }
         *isSupported = hResult;
-        return OK;
+        return DrmStatus(OK);
     } else if (mimeType == "") {
-        return BAD_VALUE;
+        return DrmStatus(BAD_VALUE);
     }
 
     sp<drm::V1_2::IDrmFactory> factoryV1_2 = drm::V1_2::IDrmFactory::castFrom(factory);
     if (factoryV1_2 == NULL) {
-        return ERROR_UNSUPPORTED;
+        return DrmStatus(ERROR_UNSUPPORTED);
     } else {
         auto hResult = factoryV1_2->isCryptoSchemeSupported_1_2(uuid, mimeType.string(),
                                                                 toHidlSecurityLevel(level));
         if (!hResult.isOk()) {
-            return DEAD_OBJECT;
+            return DrmStatus(DEAD_OBJECT);
         }
         *isSupported = hResult;
-        return OK;
+        return DrmStatus(OK);
     }
 }
 
-status_t DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
-                                             DrmPlugin::SecurityLevel level, bool* isSupported) {
+DrmStatus DrmHalHidl::isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel level, bool* isSupported) {
     Mutex::Autolock autoLock(mLock);
     *isSupported = false;
     for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
@@ -550,12 +551,13 @@
             return matchMimeTypeAndSecurityLevel(mFactories[i], uuid, mimeType, level, isSupported);
         }
     }
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
+DrmStatus DrmHalHidl::createPlugin(const uint8_t uuid[16], const String8& appPackageName) {
     Mutex::Autolock autoLock(mLock);
 
+    if (mInitCheck == ERROR_UNSUPPORTED) return mInitCheck;
     for (ssize_t i = mFactories.size() - 1; i >= 0; i--) {
         auto hResult = mFactories[i]->isCryptoSchemeSupported(uuid);
         if (hResult.isOk() && hResult) {
@@ -590,15 +592,15 @@
         }
     }
 
-    return mInitCheck;
+    return DrmStatus(mInitCheck);
 }
 
-status_t DrmHalHidl::destroyPlugin() {
+DrmStatus DrmHalHidl::destroyPlugin() {
     cleanup();
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
+DrmStatus DrmHalHidl::openSession(DrmPlugin::SecurityLevel level, Vector<uint8_t>& sessionId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -613,7 +615,7 @@
         }
     }
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
     bool retry = true;
     do {
         hidl_vec<uint8_t> hSessionId;
@@ -666,7 +668,7 @@
     return err;
 }
 
-status_t DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
+DrmStatus DrmHalHidl::closeSession(Vector<uint8_t> const& sessionId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -681,13 +683,13 @@
                 }
             }
         }
-        status_t response = toStatusT(status);
+        DrmStatus response = toStatusT(status);
         mMetrics.SetSessionEnd(sessionId);
         mMetrics.mCloseSessionCounter.Increment(response);
         return response;
     }
     mMetrics.mCloseSessionCounter.Increment(DEAD_OBJECT);
-    return DEAD_OBJECT;
+    return DrmStatus(DEAD_OBJECT);
 }
 
 static DrmPlugin::KeyRequestType toKeyRequestType(KeyRequestType keyRequestType) {
@@ -721,12 +723,12 @@
     }
 }
 
-status_t DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
-                                   Vector<uint8_t> const& initData, String8 const& mimeType,
-                                   DrmPlugin::KeyType keyType,
-                                   KeyedVector<String8, String8> const& optionalParameters,
-                                   Vector<uint8_t>& request, String8& defaultUrl,
-                                   DrmPlugin::KeyRequestType* keyRequestType) {
+DrmStatus DrmHalHidl::getKeyRequest(Vector<uint8_t> const& sessionId,
+                                    Vector<uint8_t> const& initData, String8 const& mimeType,
+                                    DrmPlugin::KeyType keyType,
+                                    KeyedVector<String8, String8> const& optionalParameters,
+                                    Vector<uint8_t>& request, String8& defaultUrl,
+                                    DrmPlugin::KeyRequestType* keyRequestType) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
     EventTimer<status_t> keyRequestTimer(&mMetrics.mGetKeyRequestTimeUs);
@@ -747,7 +749,7 @@
 
     ::KeyedVector hOptionalParameters = toHidlKeyedVector(optionalParameters);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
     Return<void> hResult;
 
     if (mPluginV1_2 != NULL) {
@@ -796,16 +798,16 @@
     return err;
 }
 
-status_t DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
-                                        Vector<uint8_t> const& response,
-                                        Vector<uint8_t>& keySetId) {
+DrmStatus DrmHalHidl::provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                         Vector<uint8_t> const& response,
+                                         Vector<uint8_t>& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
     EventTimer<status_t> keyResponseTimer(&mMetrics.mProvideKeyResponseTimeUs);
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult =
             mPlugin->provideKeyResponse(toHidlVec(sessionId), toHidlVec(response),
@@ -820,27 +822,27 @@
     return err;
 }
 
-status_t DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::removeKeys(Vector<uint8_t> const& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     Return<Status> status = mPlugin->removeKeys(toHidlVec(keySetId));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
-                                 Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::restoreKeys(Vector<uint8_t> const& sessionId,
+                                  Vector<uint8_t> const& keySetId) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
     Return<Status> status = mPlugin->restoreKeys(toHidlVec(sessionId), toHidlVec(keySetId));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
-                                    KeyedVector<String8, String8>& infoMap) const {
+DrmStatus DrmHalHidl::queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                     KeyedVector<String8, String8>& infoMap) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -848,7 +850,7 @@
 
     ::KeyedVector hInfoMap;
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->queryKeyStatus(
             toHidlVec(sessionId), [&](Status status, const hidl_vec<KeyValue>& map) {
@@ -858,15 +860,15 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? DrmStatus(err) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
-                                         Vector<uint8_t>& request, String8& defaultUrl) {
+DrmStatus DrmHalHidl::getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+                                          Vector<uint8_t>& request, String8& defaultUrl) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
     Return<void> hResult;
 
     if (mPluginV1_2 != NULL) {
@@ -897,13 +899,13 @@
     return err;
 }
 
-status_t DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
-                                              Vector<uint8_t>& certificate,
-                                              Vector<uint8_t>& wrappedKey) {
+DrmStatus DrmHalHidl::provideProvisionResponse(Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& certificate,
+                                               Vector<uint8_t>& wrappedKey) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->provideProvisionResponse(
             toHidlVec(response), [&](Status status, const hidl_vec<uint8_t>& hCertificate,
@@ -920,11 +922,11 @@
     return err;
 }
 
-status_t DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+DrmStatus DrmHalHidl::getSecureStops(List<Vector<uint8_t>>& secureStops) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult =
             mPlugin->getSecureStops([&](Status status, const hidl_vec<SecureStop>& hSecureStops) {
@@ -934,10 +936,10 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+DrmStatus DrmHalHidl::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -948,7 +950,7 @@
         return ERROR_DRM_CANNOT_HANDLE;
     }
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPluginV1_1->getSecureStopIds(
             [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
@@ -958,14 +960,14 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
+DrmStatus DrmHalHidl::getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->getSecureStop(
             toHidlVec(ssid), [&](Status status, const SecureStop& hSecureStop) {
@@ -975,10 +977,10 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+DrmStatus DrmHalHidl::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -990,10 +992,10 @@
     } else {
         status = mPlugin->releaseSecureStop(toHidlVec(ssRelease));
     }
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
+DrmStatus DrmHalHidl::removeSecureStop(Vector<uint8_t> const& ssid) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
@@ -1005,10 +1007,10 @@
     }
 
     Return<Status> status = mPluginV1_1->removeSecureStop(toHidlVec(ssid));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::removeAllSecureStops() {
+DrmStatus DrmHalHidl::removeAllSecureStops() {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1018,18 +1020,18 @@
     } else {
         status = mPlugin->releaseAllSecureStops();
     }
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
-                                   DrmPlugin::HdcpLevel* max) const {
+DrmStatus DrmHalHidl::getHdcpLevels(DrmPlugin::HdcpLevel* connected,
+                                    DrmPlugin::HdcpLevel* max) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     if (connected == NULL || max == NULL) {
         return BAD_VALUE;
     }
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     *connected = DrmPlugin::kHdcpLevelUnknown;
     *max = DrmPlugin::kHdcpLevelUnknown;
@@ -1055,26 +1057,26 @@
                     err = toStatusT(status);
                 });
     } else {
-        return ERROR_DRM_CANNOT_HANDLE;
+        return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
     }
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
+DrmStatus DrmHalHidl::getNumberOfSessions(uint32_t* open, uint32_t* max) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     if (open == NULL || max == NULL) {
         return BAD_VALUE;
     }
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     *open = 0;
     *max = 0;
 
     if (mPluginV1_1 == NULL) {
-        return ERROR_DRM_CANNOT_HANDLE;
+        return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
     }
 
     Return<void> hResult =
@@ -1086,21 +1088,21 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
-                                      DrmPlugin::SecurityLevel* level) const {
+DrmStatus DrmHalHidl::getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                       DrmPlugin::SecurityLevel* level) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     if (level == NULL) {
-        return BAD_VALUE;
+        return DrmStatus(BAD_VALUE);
     }
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     if (mPluginV1_1 == NULL) {
-        return ERROR_DRM_CANNOT_HANDLE;
+        return DrmStatus(ERROR_DRM_CANNOT_HANDLE);
     }
 
     *level = DrmPlugin::kSecurityLevelUnknown;
@@ -1113,21 +1115,21 @@
                                                              err = toStatusT(status);
                                                          });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+DrmStatus DrmHalHidl::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
-        return mInitCheck;
+        return DrmStatus(mInitCheck);
     }
 
     if (mPluginV1_2 == NULL) {
-        return ERROR_UNSUPPORTED;
+        return DrmStatus(ERROR_UNSUPPORTED);
     }
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPluginV1_2->getOfflineLicenseKeySetIds(
             [&](Status status, const hidl_vec<KeySetId>& hKeySetIds) {
@@ -1137,38 +1139,38 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+DrmStatus DrmHalHidl::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
-        return mInitCheck;
+        return DrmStatus(mInitCheck);
     }
 
     if (mPluginV1_2 == NULL) {
-        return ERROR_UNSUPPORTED;
+        return DrmStatus(ERROR_UNSUPPORTED);
     }
 
     Return<Status> status = mPluginV1_2->removeOfflineLicense(toHidlVec(keySetId));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
-                                            DrmPlugin::OfflineLicenseState* licenseState) const {
+DrmStatus DrmHalHidl::getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+                                             DrmPlugin::OfflineLicenseState* licenseState) const {
     Mutex::Autolock autoLock(mLock);
 
     if (mInitCheck != OK) {
-        return mInitCheck;
+        return DrmStatus(mInitCheck);
     }
 
     if (mPluginV1_2 == NULL) {
-        return ERROR_UNSUPPORTED;
+        return DrmStatus(ERROR_UNSUPPORTED);
     }
     *licenseState = DrmPlugin::kOfflineLicenseStateUnknown;
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPluginV1_2->getOfflineLicenseState(
             toHidlVec(keySetId), [&](Status status, OfflineLicenseState hLicenseState) {
@@ -1178,20 +1180,20 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
+DrmStatus DrmHalHidl::getPropertyString(String8 const& name, String8& value) const {
     Mutex::Autolock autoLock(mLock);
     return getPropertyStringInternal(name, value);
 }
 
-status_t DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
+DrmStatus DrmHalHidl::getPropertyStringInternal(String8 const& name, String8& value) const {
     // This function is internal to the class and should only be called while
     // mLock is already held.
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->getPropertyString(
             toHidlString(name), [&](Status status, const hidl_string& hValue) {
@@ -1201,21 +1203,21 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
+DrmStatus DrmHalHidl::getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const {
     Mutex::Autolock autoLock(mLock);
     return getPropertyByteArrayInternal(name, value);
 }
 
-status_t DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
-                                                  Vector<uint8_t>& value) const {
+DrmStatus DrmHalHidl::getPropertyByteArrayInternal(String8 const& name,
+                                                   Vector<uint8_t>& value) const {
     // This function is internal to the class and should only be called while
     // mLock is already held.
     INIT_CHECK();
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->getPropertyByteArray(
             toHidlString(name), [&](Status status, const hidl_vec<uint8_t>& hValue) {
@@ -1232,25 +1234,26 @@
     return err;
 }
 
-status_t DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
+DrmStatus DrmHalHidl::setPropertyString(String8 const& name, String8 const& value) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     Return<Status> status = mPlugin->setPropertyString(toHidlString(name), toHidlString(value));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const {
+DrmStatus DrmHalHidl::setPropertyByteArray(String8 const& name,
+                                           Vector<uint8_t> const& value) const {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     Return<Status> status = mPlugin->setPropertyByteArray(toHidlString(name), toHidlVec(value));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+DrmStatus DrmHalHidl::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
     if (consumer == nullptr) {
-        return UNEXPECTED_NULL;
+        return DrmStatus(UNEXPECTED_NULL);
     }
     consumer->consumeFrameworkMetrics(mMetrics);
 
@@ -1271,7 +1274,7 @@
         vendor += description;
 
         hidl_vec<DrmMetricGroup> pluginMetrics;
-        status_t err = UNKNOWN_ERROR;
+        DrmStatus err = UNKNOWN_ERROR;
 
         Return<void> status =
                 mPluginV1_1->getMetrics([&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
@@ -1282,14 +1285,14 @@
                     }
                     err = toStatusT(status);
                 });
-        return status.isOk() ? err : DEAD_OBJECT;
+        return status.isOk() ? err : DrmStatus(DEAD_OBJECT);
     }
 
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
-                                        String8 const& algorithm) {
+DrmStatus DrmHalHidl::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                         String8 const& algorithm) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
@@ -1297,28 +1300,28 @@
 
     Return<Status> status =
             mPlugin->setCipherAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
+DrmStatus DrmHalHidl::setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
     Return<Status> status = mPlugin->setMacAlgorithm(toHidlVec(sessionId), toHidlString(algorithm));
-    return status.isOk() ? toStatusT(status) : DEAD_OBJECT;
+    return status.isOk() ? DrmStatus(toStatusT(status)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                             Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                             Vector<uint8_t>& output) {
+DrmStatus DrmHalHidl::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult =
             mPlugin->encrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
@@ -1329,18 +1332,18 @@
                                  err = toStatusT(status);
                              });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                             Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                             Vector<uint8_t>& output) {
+DrmStatus DrmHalHidl::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult =
             mPlugin->decrypt(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(input),
@@ -1351,17 +1354,17 @@
                                  err = toStatusT(status);
                              });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                          Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+DrmStatus DrmHalHidl::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                           Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->sign(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
                                          [&](Status status, const hidl_vec<uint8_t>& hSignature) {
@@ -1371,18 +1374,18 @@
                                              err = toStatusT(status);
                                          });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                            Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
-                            bool& match) {
+DrmStatus DrmHalHidl::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                             Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                             bool& match) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult =
             mPlugin->verify(toHidlVec(sessionId), toHidlVec(keyId), toHidlVec(message),
@@ -1395,18 +1398,18 @@
                                 err = toStatusT(status);
                             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
-                             Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
-                             Vector<uint8_t>& signature) {
+DrmStatus DrmHalHidl::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                              Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+                              Vector<uint8_t>& signature) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
     DrmSessionManager::Instance()->useSession(sessionId);
 
-    status_t err = UNKNOWN_ERROR;
+    DrmStatus err = UNKNOWN_ERROR;
 
     Return<void> hResult = mPlugin->signRSA(
             toHidlVec(sessionId), toHidlString(algorithm), toHidlVec(message),
@@ -1417,7 +1420,7 @@
                 err = toStatusT(status);
             });
 
-    return hResult.isOk() ? err : DEAD_OBJECT;
+    return hResult.isOk() ? err : DrmStatus(DEAD_OBJECT);
 }
 
 std::string DrmHalHidl::reportFrameworkMetrics(const std::string& pluginMetrics) const {
@@ -1476,55 +1479,56 @@
     return metricsString;
 }
 
-status_t DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
+DrmStatus DrmHalHidl::requiresSecureDecoder(const char* mime, bool* required) const {
     Mutex::Autolock autoLock(mLock);
     if (mPluginV1_4 == NULL) {
-        return false;
+        return DrmStatus(false);
     }
     auto hResult = mPluginV1_4->requiresSecureDecoderDefault(hidl_string(mime));
     if (!hResult.isOk()) {
         DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
-        return DEAD_OBJECT;
+        return DrmStatus(DEAD_OBJECT);
     }
     if (required) {
         *required = hResult;
     }
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalHidl::requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
-                                           bool* required) const {
+DrmStatus DrmHalHidl::requiresSecureDecoder(const char* mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool* required) const {
     Mutex::Autolock autoLock(mLock);
     if (mPluginV1_4 == NULL) {
-        return false;
+        return DrmStatus(false);
     }
     auto hLevel = toHidlSecurityLevel(securityLevel);
     auto hResult = mPluginV1_4->requiresSecureDecoder(hidl_string(mime), hLevel);
     if (!hResult.isOk()) {
         DrmUtils::LOG2BE("requiresSecureDecoder txn failed: %s", hResult.description().c_str());
-        return DEAD_OBJECT;
+        return DrmStatus(DEAD_OBJECT);
     }
     if (required) {
         *required = hResult;
     }
-    return OK;
+    return DrmStatus(OK);
 }
 
-status_t DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
+DrmStatus DrmHalHidl::setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId) {
     Mutex::Autolock autoLock(mLock);
     if (mPluginV1_4 == NULL) {
-        return ERROR_UNSUPPORTED;
+        return DrmStatus(ERROR_UNSUPPORTED);
     }
     auto err = mPluginV1_4->setPlaybackId(toHidlVec(sessionId), hidl_string(playbackId));
-    return err.isOk() ? toStatusT(err) : DEAD_OBJECT;
+    return err.isOk() ? DrmStatus(toStatusT(err)) : DrmStatus(DEAD_OBJECT);
 }
 
-status_t DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+DrmStatus DrmHalHidl::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
     Mutex::Autolock autoLock(mLock);
-    return DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs);
+    return DrmStatus(DrmUtils::GetLogMessages<drm::V1_4::IDrmPlugin>(mPlugin, logs));
 }
 
-status_t DrmHalHidl::getSupportedSchemes(std::vector<uint8_t> &schemes) const {
+DrmStatus DrmHalHidl::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
     Mutex::Autolock autoLock(mLock);
     for (auto &factory : mFactories) {
         sp<drm::V1_3::IDrmFactory> factoryV1_3 = drm::V1_3::IDrmFactory::castFrom(factory);
@@ -1540,7 +1544,7 @@
             });
     }
 
-    return OK;
+    return DrmStatus(OK);
 }
 
 }  // namespace android
diff --git a/drm/libmediadrm/DrmHalListener.cpp b/drm/libmediadrm/DrmHalListener.cpp
index cfcf475..4e868ac 100644
--- a/drm/libmediadrm/DrmHalListener.cpp
+++ b/drm/libmediadrm/DrmHalListener.cpp
@@ -37,12 +37,12 @@
     return vec;
 }
 
-DrmHalListener::DrmHalListener(MediaDrmMetrics* metrics)
+DrmHalListener::DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& metrics)
     : mMetrics(metrics) {}
 
 DrmHalListener::~DrmHalListener() {}
 
-void DrmHalListener::setListener(sp<IDrmClient> listener) {
+void DrmHalListener::setListener(const sp<IDrmClient>& listener) {
     Mutex::Autolock lock(mEventLock);
     mListener = listener;
 }
diff --git a/drm/libmediadrm/DrmMetricsLogger.cpp b/drm/libmediadrm/DrmMetricsLogger.cpp
new file mode 100644
index 0000000..bc004c8
--- /dev/null
+++ b/drm/libmediadrm/DrmMetricsLogger.cpp
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "DrmMetricsLogger"
+
+#include <media/MediaMetrics.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/foundation/base64.h>
+#include <mediadrm/DrmHal.h>
+#include <mediadrm/DrmMetricsLogger.h>
+#include <mediadrm/DrmUtils.h>
+
+namespace android {
+
+namespace {
+
+std::vector<uint8_t> toStdVec(Vector<uint8_t> const& sessionId) {
+    auto sessionKey = sessionId.array();
+    std::vector<uint8_t> vec(sessionKey, sessionKey + sessionId.size());
+    return vec;
+}
+
+}  // namespace
+
+DrmMetricsLogger::DrmMetricsLogger(IDrmFrontend frontend)
+    : mImpl(sp<DrmHal>::make()), mUuid(), mObjNonce(), mFrontend(frontend) {}
+
+DrmMetricsLogger::~DrmMetricsLogger() {}
+
+int MediaErrorToJavaError(status_t err) {
+#define STATUS_CASE(status) \
+    case status: \
+        return J##status
+
+    switch (err) {
+        STATUS_CASE(ERROR_DRM_UNKNOWN);
+        STATUS_CASE(ERROR_DRM_NO_LICENSE);
+        STATUS_CASE(ERROR_DRM_LICENSE_EXPIRED);
+        STATUS_CASE(ERROR_DRM_RESOURCE_BUSY);
+        STATUS_CASE(ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION);
+        STATUS_CASE(ERROR_DRM_SESSION_NOT_OPENED);
+        STATUS_CASE(ERROR_DRM_CANNOT_HANDLE);
+        STATUS_CASE(ERROR_DRM_INSUFFICIENT_SECURITY);
+        STATUS_CASE(ERROR_DRM_FRAME_TOO_LARGE);
+        STATUS_CASE(ERROR_DRM_SESSION_LOST_STATE);
+        STATUS_CASE(ERROR_DRM_CERTIFICATE_MALFORMED);
+        STATUS_CASE(ERROR_DRM_CERTIFICATE_MISSING);
+        STATUS_CASE(ERROR_DRM_CRYPTO_LIBRARY);
+        STATUS_CASE(ERROR_DRM_GENERIC_OEM);
+        STATUS_CASE(ERROR_DRM_GENERIC_PLUGIN);
+        STATUS_CASE(ERROR_DRM_INIT_DATA);
+        STATUS_CASE(ERROR_DRM_KEY_NOT_LOADED);
+        STATUS_CASE(ERROR_DRM_LICENSE_PARSE);
+        STATUS_CASE(ERROR_DRM_LICENSE_POLICY);
+        STATUS_CASE(ERROR_DRM_LICENSE_RELEASE);
+        STATUS_CASE(ERROR_DRM_LICENSE_REQUEST_REJECTED);
+        STATUS_CASE(ERROR_DRM_LICENSE_RESTORE);
+        STATUS_CASE(ERROR_DRM_LICENSE_STATE);
+        STATUS_CASE(ERROR_DRM_MEDIA_FRAMEWORK);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_CERTIFICATE);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_CONFIG);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_PARSE);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_REQUEST_REJECTED);
+        STATUS_CASE(ERROR_DRM_PROVISIONING_RETRY);
+        STATUS_CASE(ERROR_DRM_RESOURCE_CONTENTION);
+        STATUS_CASE(ERROR_DRM_SECURE_STOP_RELEASE);
+        STATUS_CASE(ERROR_DRM_STORAGE_READ);
+        STATUS_CASE(ERROR_DRM_STORAGE_WRITE);
+        STATUS_CASE(ERROR_DRM_ZERO_SUBSAMPLES);
+#undef STATUS_CASE
+    }
+    return static_cast<int>(err);
+}
+
+int DrmPluginSecurityLevelToJavaSecurityLevel(DrmPlugin::SecurityLevel securityLevel) {
+#define STATUS_CASE(status) \
+    case DrmPlugin::k##status: \
+        return J##status
+
+    switch (securityLevel) {
+        STATUS_CASE(SecurityLevelUnknown);
+        STATUS_CASE(SecurityLevelSwSecureCrypto);
+        STATUS_CASE(SecurityLevelSwSecureDecode);
+        STATUS_CASE(SecurityLevelHwSecureCrypto);
+        STATUS_CASE(SecurityLevelHwSecureDecode);
+        STATUS_CASE(SecurityLevelHwSecureAll);
+        STATUS_CASE(SecurityLevelMax);
+#undef STATUS_CASE
+    }
+    return static_cast<int>(securityLevel);
+}
+
+
+DrmStatus DrmMetricsLogger::initCheck() const {
+    DrmStatus status = mImpl->initCheck();
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
+                                                    const String8& mimeType,
+                                                    DrmPlugin::SecurityLevel securityLevel,
+                                                    bool* result) {
+    DrmStatus status = mImpl->isCryptoSchemeSupported(uuid, mimeType, securityLevel, result);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
+                                         const String8& appPackageName) {
+    std::memcpy(mUuid.data(), uuid, IDRM_UUID_SIZE);
+    mUuid[0] = betoh64(mUuid[0]);
+    mUuid[1] = betoh64(mUuid[1]);
+    if (kUuidSchemeMap.count(mUuid)) {
+        mScheme = kUuidSchemeMap.at(mUuid);
+    } else {
+        mScheme = "Other";
+    }
+    if (generateNonce(&mObjNonce, kNonceSize, __func__) != OK) {
+        return ERROR_DRM_RESOURCE_BUSY;
+    }
+    DrmStatus status = mImpl->createPlugin(uuid, appPackageName);
+    if (status == OK) {
+        String8 version8;
+        if (getPropertyString(String8("version"), version8) == OK) {
+            mVersion = version8.string();
+        }
+        reportMediaDrmCreated();
+    } else {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::destroyPlugin() {
+    DrmStatus status = mImpl->destroyPlugin();
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::openSession(DrmPlugin::SecurityLevel securityLevel,
+                                        Vector<uint8_t>& sessionId) {
+    SessionContext ctx{};
+    if (generateNonce(&ctx.mNonce, kNonceSize, __func__) != OK) {
+        return ERROR_DRM_RESOURCE_BUSY;
+    }
+    DrmStatus status = mImpl->openSession(securityLevel, sessionId);
+    if (status == OK) {
+        std::vector<uint8_t> sessionKey = toStdVec(sessionId);
+        ctx.mTargetSecurityLevel = securityLevel;
+        if (getSecurityLevel(sessionId, &ctx.mActualSecurityLevel) != OK) {
+            ctx.mActualSecurityLevel = DrmPlugin::kSecurityLevelUnknown;
+        }
+        if (!mVersion.empty()) {
+            ctx.mVersion = mVersion;
+        }
+        {
+            const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+            mSessionMap.insert({sessionKey, ctx});
+        }
+        reportMediaDrmSessionOpened(sessionKey);
+    } else {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::closeSession(Vector<uint8_t> const& sessionId) {
+    std::vector<uint8_t> sid = toStdVec(sessionId);
+    {
+        const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+        mSessionMap.erase(sid);
+    }
+    DrmStatus status = mImpl->closeSession(sessionId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, sid);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getKeyRequest(Vector<uint8_t> const& sessionId,
+                                          Vector<uint8_t> const& initData, String8 const& mimeType,
+                                          DrmPlugin::KeyType keyType,
+                                          KeyedVector<String8, String8> const& optionalParameters,
+                                          Vector<uint8_t>& request, String8& defaultUrl,
+                                          DrmPlugin::KeyRequestType* keyRequestType) {
+    DrmStatus status =
+            mImpl->getKeyRequest(sessionId, initData, mimeType, keyType, optionalParameters,
+                                 request, defaultUrl, keyRequestType);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                               Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& keySetId) {
+    DrmStatus status = mImpl->provideKeyResponse(sessionId, response, keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeKeys(Vector<uint8_t> const& keySetId) {
+    DrmStatus status = mImpl->removeKeys(keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::restoreKeys(Vector<uint8_t> const& sessionId,
+                                        Vector<uint8_t> const& keySetId) {
+    DrmStatus status = mImpl->restoreKeys(sessionId, keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                           KeyedVector<String8, String8>& infoMap) const {
+    DrmStatus status = mImpl->queryKeyStatus(sessionId, infoMap);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getProvisionRequest(String8 const& certType,
+                                                String8 const& certAuthority,
+                                                Vector<uint8_t>& request, String8& defaultUrl) {
+    DrmStatus status = mImpl->getProvisionRequest(certType, certAuthority, request, defaultUrl);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::provideProvisionResponse(Vector<uint8_t> const& response,
+                                                     Vector<uint8_t>& certificate,
+                                                     Vector<uint8_t>& wrappedKey) {
+    DrmStatus status = mImpl->provideProvisionResponse(response, certificate, wrappedKey);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStops(List<Vector<uint8_t>>& secureStops) {
+    DrmStatus status = mImpl->getSecureStops(secureStops);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStopIds(List<Vector<uint8_t>>& secureStopIds) {
+    DrmStatus status = mImpl->getSecureStopIds(secureStopIds);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecureStop(Vector<uint8_t> const& ssid,
+                                          Vector<uint8_t>& secureStop) {
+    DrmStatus status = mImpl->getSecureStop(ssid, secureStop);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::releaseSecureStops(Vector<uint8_t> const& ssRelease) {
+    DrmStatus status = mImpl->releaseSecureStops(ssRelease);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeSecureStop(Vector<uint8_t> const& ssid) {
+    DrmStatus status = mImpl->removeSecureStop(ssid);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeAllSecureStops() {
+    DrmStatus status = mImpl->removeAllSecureStops();
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+                                          DrmPlugin::HdcpLevel* maxLevel) const {
+    DrmStatus status = mImpl->getHdcpLevels(connectedLevel, maxLevel);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getNumberOfSessions(uint32_t* currentSessions,
+                                                uint32_t* maxSessions) const {
+    DrmStatus status = mImpl->getNumberOfSessions(currentSessions, maxSessions);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                             DrmPlugin::SecurityLevel* level) const {
+    DrmStatus status = mImpl->getSecurityLevel(sessionId, level);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const {
+    DrmStatus status = mImpl->getOfflineLicenseKeySetIds(keySetIds);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::removeOfflineLicense(Vector<uint8_t> const& keySetId) {
+    DrmStatus status = mImpl->removeOfflineLicense(keySetId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getOfflineLicenseState(
+        Vector<uint8_t> const& keySetId, DrmPlugin::OfflineLicenseState* licenseState) const {
+    DrmStatus status = mImpl->getOfflineLicenseState(keySetId, licenseState);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getPropertyString(String8 const& name, String8& value) const {
+    DrmStatus status = mImpl->getPropertyString(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getPropertyByteArray(String8 const& name,
+                                                 Vector<uint8_t>& value) const {
+    DrmStatus status = mImpl->getPropertyByteArray(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setPropertyString(String8 const& name, String8 const& value) const {
+    DrmStatus status = mImpl->setPropertyString(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setPropertyByteArray(String8 const& name,
+                                                 Vector<uint8_t> const& value) const {
+    DrmStatus status = mImpl->setPropertyByteArray(name, value);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getMetrics(const sp<IDrmMetricsConsumer>& consumer) {
+    DrmStatus status = mImpl->getMetrics(consumer);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                               String8 const& algorithm) {
+    DrmStatus status = mImpl->setCipherAlgorithm(sessionId, algorithm);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setMacAlgorithm(Vector<uint8_t> const& sessionId,
+                                            String8 const& algorithm) {
+    DrmStatus status = mImpl->setMacAlgorithm(sessionId, algorithm);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                    Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                                    Vector<uint8_t>& output) {
+    DrmStatus status = mImpl->encrypt(sessionId, keyId, input, iv, output);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                    Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                                    Vector<uint8_t>& output) {
+    DrmStatus status = mImpl->decrypt(sessionId, keyId, input, iv, output);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                 Vector<uint8_t> const& message, Vector<uint8_t>& signature) {
+    DrmStatus status = mImpl->sign(sessionId, keyId, message, signature);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                                   Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                                   bool& match) {
+    DrmStatus status = mImpl->verify(sessionId, keyId, message, signature, match);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                                    Vector<uint8_t> const& message,
+                                    Vector<uint8_t> const& wrappedKey, Vector<uint8_t>& signature) {
+    DrmStatus status = mImpl->signRSA(sessionId, algorithm, message, wrappedKey, signature);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setListener(const sp<IDrmClient>& listener) {
+    DrmStatus status = mImpl->setListener(listener);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime, bool* required) const {
+    DrmStatus status = mImpl->requiresSecureDecoder(mime, required);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::requiresSecureDecoder(const char* mime,
+                                                  DrmPlugin::SecurityLevel securityLevel,
+                                                  bool* required) const {
+    DrmStatus status = mImpl->requiresSecureDecoder(mime, securityLevel, required);
+    if (status != OK) {
+        reportMediaDrmErrored(status, "requiresSecureDecoderLevel");
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::setPlaybackId(Vector<uint8_t> const& sessionId,
+                                          const char* playbackId) {
+    DrmStatus status = mImpl->setPlaybackId(sessionId, playbackId);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__, toStdVec(sessionId));
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const {
+    DrmStatus status = mImpl->getLogMessages(logs);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+DrmStatus DrmMetricsLogger::getSupportedSchemes(std::vector<uint8_t>& schemes) const {
+    DrmStatus status = mImpl->getSupportedSchemes(schemes);
+    if (status != OK) {
+        reportMediaDrmErrored(status, __func__);
+    }
+    return status;
+}
+
+void DrmMetricsLogger::reportMediaDrmCreated() const {
+    mediametrics_handle_t handle(mediametrics_create("mediadrm.created"));
+    mediametrics_setCString(handle, "scheme", mScheme.c_str());
+    mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+    mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
+    mediametrics_setInt32(handle, "frontend", mFrontend);
+    mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
+    mediametrics_setCString(handle, "version", mVersion.c_str());
+    mediametrics_selfRecord(handle);
+    mediametrics_delete(handle);
+}
+
+void DrmMetricsLogger::reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const {
+    mediametrics_handle_t handle(mediametrics_create("mediadrm.session_opened"));
+    mediametrics_setCString(handle, "scheme", mScheme.c_str());
+    mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+    mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
+    mediametrics_setInt32(handle, "frontend", mFrontend);
+    mediametrics_setCString(handle, "version", mVersion.c_str());
+    mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
+    const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+    auto it = mSessionMap.find(sessionId);
+    if (it != mSessionMap.end()) {
+        mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
+        mediametrics_setInt32(handle, "requested_security_level",
+                    DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mTargetSecurityLevel));
+        mediametrics_setInt32(handle, "opened_security_level",
+                    DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mActualSecurityLevel));
+    }
+    mediametrics_selfRecord(handle);
+    mediametrics_delete(handle);
+}
+
+void DrmMetricsLogger::reportMediaDrmErrored(const DrmStatus& error_code, const char* api,
+                                             const std::vector<uint8_t>& sessionId) const {
+    mediametrics_handle_t handle(mediametrics_create("mediadrm.errored"));
+    mediametrics_setCString(handle, "scheme", mScheme.c_str());
+    mediametrics_setInt64(handle, "uuid_msb", mUuid[0]);
+    mediametrics_setInt64(handle, "uuid_lsb", mUuid[1]);
+    mediametrics_setInt32(handle, "frontend", mFrontend);
+    mediametrics_setCString(handle, "version", mVersion.c_str());
+    mediametrics_setCString(handle, "object_nonce", mObjNonce.c_str());
+    if (!sessionId.empty()) {
+        const std::lock_guard<std::mutex> lock(mSessionMapMutex);
+        auto it = mSessionMap.find(sessionId);
+        if (it != mSessionMap.end()) {
+            mediametrics_setCString(handle, "session_nonce", it->second.mNonce.c_str());
+            mediametrics_setInt32(handle, "security_level",
+                        DrmPluginSecurityLevelToJavaSecurityLevel(it->second.mActualSecurityLevel));
+        }
+    }
+    mediametrics_setCString(handle, "api", api);
+    mediametrics_setInt32(handle, "error_code", MediaErrorToJavaError(error_code));
+    mediametrics_setInt32(handle, "cdm_err", error_code.getCdmErr());
+    mediametrics_setInt32(handle, "oem_err", error_code.getOemErr());
+    mediametrics_setInt32(handle, "error_context", error_code.getContext());
+    mediametrics_selfRecord(handle);
+    mediametrics_delete(handle);
+}
+
+DrmStatus DrmMetricsLogger::generateNonce(std::string* out, size_t size, const char* api) {
+    std::vector<uint8_t> buf(size);
+    ssize_t bytes = getrandom(buf.data(), size, GRND_NONBLOCK);
+    if (bytes < size) {
+        ALOGE("getrandom failed: %d", errno);
+        reportMediaDrmErrored(ERROR_DRM_RESOURCE_BUSY, api);
+        return ERROR_DRM_RESOURCE_BUSY;
+    }
+    android::AString tmp;
+    encodeBase64(buf.data(), size, &tmp);
+    out->assign(tmp.c_str());
+    return OK;
+}
+
+const std::map<std::array<int64_t, 2>, std::string> DrmMetricsLogger::kUuidSchemeMap {
+        {{(int64_t)0x6DD8B3C345F44A68, (int64_t)0xBF3A64168D01A4A6}, "ABV DRM (MoDRM)"},
+        {{(int64_t)0xF239E769EFA34850, (int64_t)0x9C16A903C6932EFB},
+         "Adobe Primetime DRM version 4"},
+        {{(int64_t)0x616C746963617374, (int64_t)0x2D50726F74656374}, "Alticast"},
+        {{(int64_t)0x94CE86FB07FF4F43, (int64_t)0xADB893D2FA968CA2}, "Apple FairPlay"},
+        {{(int64_t)0x279FE473512C48FE, (int64_t)0xADE8D176FEE6B40F}, "Arris Titanium"},
+        {{(int64_t)0x3D5E6D359B9A41E8, (int64_t)0xB843DD3C6E72C42C}, "ChinaDRM"},
+        {{(int64_t)0x3EA8778F77424BF9, (int64_t)0xB18BE834B2ACBD47}, "Clear Key AES-128"},
+        {{(int64_t)0xBE58615B19C44684, (int64_t)0x88B3C8C57E99E957}, "Clear Key SAMPLE-AES"},
+        {{(int64_t)0xE2719D58A985B3C9, (int64_t)0x781AB030AF78D30E}, "Clear Key DASH-IF"},
+        {{(int64_t)0x644FE7B5260F4FAD, (int64_t)0x949A0762FFB054B4}, "CMLA (OMA DRM)"},
+        {{(int64_t)0x37C332587B994C7E, (int64_t)0xB15D19AF74482154}, "Commscope Titanium V3"},
+        {{(int64_t)0x45D481CB8FE049C0, (int64_t)0xADA9AB2D2455B2F2}, "CoreCrypt"},
+        {{(int64_t)0xDCF4E3E362F15818, (int64_t)0x7BA60A6FE33FF3DD}, "DigiCAP SmartXess"},
+        {{(int64_t)0x35BF197B530E42D7, (int64_t)0x8B651B4BF415070F}, "DivX DRM Series 5"},
+        {{(int64_t)0x80A6BE7E14484C37, (int64_t)0x9E70D5AEBE04C8D2}, "Irdeto Content Protection"},
+        {{(int64_t)0x5E629AF538DA4063, (int64_t)0x897797FFBD9902D4},
+         "Marlin Adaptive Streaming Simple Profile V1.0"},
+        {{(int64_t)0x9A04F07998404286, (int64_t)0xAB92E65BE0885F95}, "Microsoft PlayReady"},
+        {{(int64_t)0x6A99532D869F5922, (int64_t)0x9A91113AB7B1E2F3}, "MobiTV DRM"},
+        {{(int64_t)0xADB41C242DBF4A6D, (int64_t)0x958B4457C0D27B95}, "Nagra MediaAccess PRM 3.0"},
+        {{(int64_t)0x1F83E1E86EE94F0D, (int64_t)0xBA2F5EC4E3ED1A66}, "SecureMedia"},
+        {{(int64_t)0x992C46E6C4374899, (int64_t)0xB6A050FA91AD0E39}, "SecureMedia SteelKnot"},
+        {{(int64_t)0xA68129D3575B4F1A, (int64_t)0x9CBA3223846CF7C3},
+         "Synamedia/Cisco/NDS VideoGuard DRM"},
+        {{(int64_t)0xAA11967FCC014A4A, (int64_t)0x8E99C5D3DDDFEA2D}, "Unitend DRM (UDRM)"},
+        {{(int64_t)0x9A27DD82FDE24725, (int64_t)0x8CBC4234AA06EC09}, "Verimatrix VCAS"},
+        {{(int64_t)0xB4413586C58CFFB0, (int64_t)0x94A5D4896C1AF6C3}, "Viaccess-Orca DRM (VODRM)"},
+        {{(int64_t)0x793B79569F944946, (int64_t)0xA94223E7EF7E44B4}, "VisionCrypt"},
+        {{(int64_t)0x1077EFECC0B24D02, (int64_t)0xACE33C1E52E2FB4B}, "W3C Common PSSH box"},
+        {{(int64_t)0xEDEF8BA979D64ACE, (int64_t)0xA3C827DCD51D21ED}, "Widevine Content Protection"},
+};
+
+}  // namespace android
\ No newline at end of file
diff --git a/drm/libmediadrm/DrmSessionManager.cpp b/drm/libmediadrm/DrmSessionManager.cpp
index e31395d..301538f 100644
--- a/drm/libmediadrm/DrmSessionManager.cpp
+++ b/drm/libmediadrm/DrmSessionManager.cpp
@@ -34,6 +34,7 @@
 namespace android {
 
 using aidl::android::media::MediaResourceParcel;
+using aidl::android::media::ClientInfoParcel;
 
 namespace {
 void ResourceManagerServiceDied(void* cookie) {
@@ -137,7 +138,10 @@
 
     static int64_t clientId = 0;
     mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
-    mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
+                                .uid = static_cast<int32_t>(uid),
+                                .id = clientId++};
+    mService->addResource(clientInfo, drm, toResourceVec(sessionId, INT64_MAX));
 }
 
 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
@@ -150,7 +154,10 @@
     }
 
     auto info = it->second;
-    mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId, -1));
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
+                                .uid = static_cast<int32_t>(info.uid),
+                                .id = info.clientId};
+    mService->addResource(clientInfo, NULL, toResourceVec(sessionId, -1));
 }
 
 void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
@@ -164,7 +171,10 @@
 
     auto info = it->second;
     // removeClient instead of removeSession because each client has only one session
-    mService->removeClient(info.pid, info.clientId);
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
+                                .uid = static_cast<int32_t>(info.uid),
+                                .id = info.clientId};
+    mService->removeClient(clientInfo);
     mSessionMap.erase(it);
 }
 
@@ -182,9 +192,13 @@
 
     // cannot update mSessionMap because we do not know which sessionId is reclaimed;
     // we rely on IResourceManagerClient to removeSession in reclaimResource
-    Vector<uint8_t> dummy;
+    Vector<uint8_t> placeHolder;
     bool success;
-    ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
+    uid_t uid = AIBinder_getCallingUid();
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(callingPid),
+                                .uid = static_cast<int32_t>(uid)};
+    ScopedAStatus status = service->reclaimResource(
+        clientInfo, toResourceVec(placeHolder, INT64_MAX), &success);
     return status.isOk() && success;
 }
 
diff --git a/drm/libmediadrm/DrmStatus.cpp b/drm/libmediadrm/DrmStatus.cpp
new file mode 100644
index 0000000..f622160
--- /dev/null
+++ b/drm/libmediadrm/DrmStatus.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mediadrm/DrmStatus.h>
+#include <json/json.h>
+
+namespace android {
+
+DrmStatus::DrmStatus(status_t err, const char *msg) : mStatus(err) {
+    Json::Value errorDetails;
+    Json::Reader reader;
+    if (!reader.parse(msg, errorDetails)) {
+        mErrMsg = msg;
+        return;
+    }
+
+    auto val = errorDetails["cdmError"];
+    if (val.isInt()) {
+        mCdmErr = val.asInt();
+    }
+    val = errorDetails["oemError"];
+    if (val.isInt()) {
+        mOemErr = val.asInt();
+    }
+    val = errorDetails["context"];
+    if (val.isInt()) {
+        mCtx = val.asInt();
+    }
+    val = errorDetails["errorMessage"];
+    if (val.isString()) {
+        mErrMsg = val.asString();
+    } else {
+        mErrMsg = msg;
+    }
+}
+
+}  // namespace android
diff --git a/drm/libmediadrm/DrmUtils.cpp b/drm/libmediadrm/DrmUtils.cpp
index be0cd4b..a99b1d1 100644
--- a/drm/libmediadrm/DrmUtils.cpp
+++ b/drm/libmediadrm/DrmUtils.cpp
@@ -32,6 +32,7 @@
 #include <android/hardware/drm/1.4/IDrmFactory.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
 #include <hidl/HidlSupport.h>
+#include <json/json.h>
 
 #include <cutils/properties.h>
 #include <utils/Errors.h>
@@ -58,11 +59,11 @@
 
 namespace {
 
-template <typename Hal>
-Hal* MakeObject(status_t* pstatus) {
+template <typename Hal, typename... Ts>
+Hal* MakeObject(status_t* pstatus, Ts... args) {
     status_t err = OK;
     status_t& status = pstatus ? *pstatus : err;
-    auto obj = new Hal();
+    auto obj = new Hal(args...);
     status = obj->initCheck();
     if (status != OK && status != NO_INIT) {
         return NULL;
@@ -191,8 +192,8 @@
     return factories;
 }
 
-sp<IDrm> MakeDrm(status_t* pstatus) {
-    return MakeObject<DrmHal>(pstatus);
+sp<IDrm> MakeDrm(IDrmFrontend frontend, status_t* pstatus) {
+    return MakeObject<DrmMetricsLogger>(pstatus, frontend);
 }
 
 sp<ICrypto> MakeCrypto(status_t* pstatus) {
@@ -362,18 +363,23 @@
 }
 }  // namespace
 
-std::string GetExceptionMessage(status_t err, const char* msg,
+std::string GetExceptionMessage(const DrmStatus &err, const char* defaultMsg,
                                 const Vector<::V1_4::LogMessage>& logs) {
     std::string ruler("==============================");
     std::string header("Beginning of DRM Plugin Log");
     std::string footer("End of DRM Plugin Log");
+    std::string msg(err.getErrorMessage());
     String8 msg8;
-    if (msg) {
-        msg8 += msg;
+    if (!msg.empty()) {
+        msg8 += msg.c_str();
+        msg8 += ": ";
+    } else if (defaultMsg) {
+        msg8 += defaultMsg;
         msg8 += ": ";
     }
-    auto errStr = StrCryptoError(err);
-    msg8 += errStr.c_str();
+    msg8 += StrCryptoError(err).c_str();
+    msg8 += String8::format("\ncdm err: %d, oem err: %d, ctx: %d",
+                            err.getCdmErr(), err.getOemErr(), err.getContext());
     msg8 += String8::format("\n%s %s %s", ruler.c_str(), header.c_str(), ruler.c_str());
 
     for (auto log : logs) {
@@ -410,6 +416,141 @@
     return logs;
 }
 
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl) {
+    if (statusAidl.isOk()) return OK;
+    if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
+    auto astatus = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
+    status_t status{};
+    switch (astatus) {
+    case StatusAidl::OK:
+        status = OK;
+        break;
+    case StatusAidl::BAD_VALUE:
+        status = BAD_VALUE;
+        break;
+    case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
+        status = ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case StatusAidl::ERROR_DRM_DECRYPT:
+        status = ERROR_DRM_DECRYPT;
+        break;
+    case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
+        status = ERROR_DRM_DEVICE_REVOKED;
+        break;
+    case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
+        status = ERROR_DRM_FRAME_TOO_LARGE;
+        break;
+    case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
+        status = ERROR_DRM_INSUFFICIENT_SECURITY;
+        break;
+    case StatusAidl::ERROR_DRM_INVALID_STATE:
+        status = ERROR_DRM_INVALID_STATE;
+        break;
+    case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
+        status = ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case StatusAidl::ERROR_DRM_NO_LICENSE:
+        status = ERROR_DRM_NO_LICENSE;
+        break;
+    case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
+        status = ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
+        status = ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
+        status = ERROR_DRM_RESOURCE_CONTENTION;
+        break;
+    case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
+        status = ERROR_DRM_SESSION_LOST_STATE;
+        break;
+    case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
+        status = ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+
+    // New in S / drm@1.4:
+    case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
+        status = ERROR_DRM_ZERO_SUBSAMPLES;
+        break;
+    case StatusAidl::CRYPTO_LIBRARY_ERROR:
+        status = ERROR_DRM_CRYPTO_LIBRARY;
+        break;
+    case StatusAidl::GENERAL_OEM_ERROR:
+        status = ERROR_DRM_GENERIC_OEM;
+        break;
+    case StatusAidl::GENERAL_PLUGIN_ERROR:
+        status = ERROR_DRM_GENERIC_PLUGIN;
+        break;
+    case StatusAidl::INIT_DATA_INVALID:
+        status = ERROR_DRM_INIT_DATA;
+        break;
+    case StatusAidl::KEY_NOT_LOADED:
+        status = ERROR_DRM_KEY_NOT_LOADED;
+        break;
+    case StatusAidl::LICENSE_PARSE_ERROR:
+        status = ERROR_DRM_LICENSE_PARSE;
+        break;
+    case StatusAidl::LICENSE_POLICY_ERROR:
+        status = ERROR_DRM_LICENSE_POLICY;
+        break;
+    case StatusAidl::LICENSE_RELEASE_ERROR:
+        status = ERROR_DRM_LICENSE_RELEASE;
+        break;
+    case StatusAidl::LICENSE_REQUEST_REJECTED:
+        status = ERROR_DRM_LICENSE_REQUEST_REJECTED;
+        break;
+    case StatusAidl::LICENSE_RESTORE_ERROR:
+        status = ERROR_DRM_LICENSE_RESTORE;
+        break;
+    case StatusAidl::LICENSE_STATE_ERROR:
+        status = ERROR_DRM_LICENSE_STATE;
+        break;
+    case StatusAidl::MALFORMED_CERTIFICATE:
+        status = ERROR_DRM_CERTIFICATE_MALFORMED;
+        break;
+    case StatusAidl::MEDIA_FRAMEWORK_ERROR:
+        status = ERROR_DRM_MEDIA_FRAMEWORK;
+        break;
+    case StatusAidl::MISSING_CERTIFICATE:
+        status = ERROR_DRM_CERTIFICATE_MISSING;
+        break;
+    case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
+        status = ERROR_DRM_PROVISIONING_CERTIFICATE;
+        break;
+    case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
+        status = ERROR_DRM_PROVISIONING_CONFIG;
+        break;
+    case StatusAidl::PROVISIONING_PARSE_ERROR:
+        status = ERROR_DRM_PROVISIONING_PARSE;
+        break;
+    case StatusAidl::PROVISIONING_REQUEST_REJECTED:
+        status = ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
+        break;
+    case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
+        status = ERROR_DRM_PROVISIONING_RETRY;
+        break;
+    case StatusAidl::SECURE_STOP_RELEASE_ERROR:
+        status = ERROR_DRM_SECURE_STOP_RELEASE;
+        break;
+    case StatusAidl::STORAGE_READ_FAILURE:
+        status = ERROR_DRM_STORAGE_READ;
+        break;
+    case StatusAidl::STORAGE_WRITE_FAILURE:
+        status = ERROR_DRM_STORAGE_WRITE;
+        break;
+
+    case StatusAidl::ERROR_DRM_UNKNOWN:
+    default:
+        status = ERROR_DRM_UNKNOWN;
+        break;
+    }
+
+    return DrmStatus(status, statusAidl.getMessage());
+}
+
 LogBuffer gLogBuf;
 }  // namespace DrmUtils
 }  // namespace android
diff --git a/drm/libmediadrm/fuzzer/Android.bp b/drm/libmediadrm/fuzzer/Android.bp
index a85e3cf..deda9ef 100644
--- a/drm/libmediadrm/fuzzer/Android.bp
+++ b/drm/libmediadrm/fuzzer/Android.bp
@@ -37,6 +37,7 @@
         "liblog",
         "resourcemanager_aidl_interface-ndk",
         "libaidlcommonsupport",
+        "libjsoncpp",
     ],
     header_libs: [
         "libmedia_headers",
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHal.h b/drm/libmediadrm/include/mediadrm/CryptoHal.h
index 32a6741..60cbbf8 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHal.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHal.h
@@ -38,7 +38,7 @@
     virtual bool requiresSecureDecoderComponent(
             const char *mime) const;
     virtual void notifyResolution(uint32_t width, uint32_t height);
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
             const drm::V1_0::SharedBuffer &source, size_t offset,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
index 50878a6..eec4585 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalAidl.h
@@ -49,7 +49,7 @@
     virtual status_t destroyPlugin();
     virtual bool requiresSecureDecoderComponent(const char* mime) const;
     virtual void notifyResolution(uint32_t width, uint32_t height);
-    virtual status_t setMediaDrmSession(const Vector<uint8_t>& sessionId);
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t>& sessionId);
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode,
                             const CryptoPlugin::Pattern& pattern, const ::SharedBuffer& source,
                             size_t offset, const CryptoPlugin::SubSample* subSamples,
diff --git a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
index 6db1e89..0150d7c 100644
--- a/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/CryptoHalHidl.h
@@ -57,7 +57,7 @@
 
     virtual void notifyResolution(uint32_t width, uint32_t height);
 
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId);
 
     virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
             CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
diff --git a/drm/libmediadrm/include/mediadrm/DrmHal.h b/drm/libmediadrm/include/mediadrm/DrmHal.h
index eab597b..16e5fe1 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHal.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHal.h
@@ -15,6 +15,7 @@
  */
 
 #include <mediadrm/IDrm.h>
+#include <mediadrm/DrmStatus.h>
 
 #ifndef DRM_HAL_H_
 #define DRM_HAL_H_
@@ -24,100 +25,99 @@
 struct DrmHal : public IDrm {
     DrmHal();
     virtual ~DrmHal();
-    virtual status_t initCheck() const;
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
-                                             const String8 &mimeType,
-                                             DrmPlugin::SecurityLevel securityLevel,
-                                             bool *result);
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8 &appPackageName);
-    virtual status_t destroyPlugin();
-    virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+    virtual DrmStatus initCheck() const;
+    virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel securityLevel, bool* result);
+    virtual DrmStatus createPlugin(const uint8_t uuid[16],
+                                   const String8 &appPackageName);
+    virtual DrmStatus destroyPlugin();
+    virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
             Vector<uint8_t> &sessionId);
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId);
-    virtual status_t
+    virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId);
+    virtual DrmStatus
         getKeyRequest(Vector<uint8_t> const &sessionId,
                       Vector<uint8_t> const &initData,
                       String8 const &mimeType, DrmPlugin::KeyType keyType,
                       KeyedVector<String8, String8> const &optionalParameters,
                       Vector<uint8_t> &request, String8 &defaultUrl,
                       DrmPlugin::KeyRequestType *keyRequestType);
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId);
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId);
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                    KeyedVector<String8, String8> &infoMap) const;
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaultUrl);
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey);
-    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
-    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
-    virtual status_t removeAllSecureStops();
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+    virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                         Vector<uint8_t> const &response,
+                                         Vector<uint8_t> &keySetId);
+    virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId);
+    virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+                                  Vector<uint8_t> const &keySetId);
+    virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+                                     KeyedVector<String8, String8> &infoMap) const;
+    virtual DrmStatus getProvisionRequest(String8 const &certType,
+                                          String8 const &certAuthority,
+                                          Vector<uint8_t> &request,
+                                          String8 &defaultUrl);
+    virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+                                               Vector<uint8_t> &certificate,
+                                               Vector<uint8_t> &wrappedKey);
+    virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops);
+    virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+    virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+    virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease);
+    virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid);
+    virtual DrmStatus removeAllSecureStops();
+    virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel) const;
-    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+    virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
             uint32_t *maxSessions) const;
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+    virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
             DrmPlugin::SecurityLevel *level) const;
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+    virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+    virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId);
+    virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
             DrmPlugin::OfflineLicenseState *licenseState) const;
-    virtual status_t getPropertyString(String8 const &name, String8 &value) const;
-    virtual status_t getPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> &value) const;
-    virtual status_t setPropertyString(String8 const &name,
-                                       String8 const &value ) const;
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value) const;
-    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm);
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm);
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+    virtual DrmStatus getPropertyString(String8 const &name, String8 &value) const;
+    virtual DrmStatus getPropertyByteArray(String8 const &name,
+                                           Vector<uint8_t> &value) const;
+    virtual DrmStatus setPropertyString(String8 const &name,
+                                        String8 const &value ) const;
+    virtual DrmStatus setPropertyByteArray(String8 const &name,
+                                           Vector<uint8_t> const &value) const;
+    virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+    virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                         String8 const &algorithm);
+    virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                      String8 const &algorithm);
+    virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &keyId,
+                              Vector<uint8_t> const &input,
+                              Vector<uint8_t> const &iv,
+                              Vector<uint8_t> &output);
+    virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &keyId,
+                              Vector<uint8_t> const &input,
+                              Vector<uint8_t> const &iv,
+                              Vector<uint8_t> &output);
+    virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+                           Vector<uint8_t> const &keyId,
+                           Vector<uint8_t> const &message,
+                           Vector<uint8_t> &signature);
+    virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
                              Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output);
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output);
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature);
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match);
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
                              Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature);
-    virtual status_t setListener(const sp<IDrmClient>& listener);
-    virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
-    virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
-                                           bool *required) const;
-    virtual status_t setPlaybackId(
+                             Vector<uint8_t> const &signature,
+                             bool &match);
+    virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+                              String8 const &algorithm,
+                              Vector<uint8_t> const &message,
+                              Vector<uint8_t> const &wrappedKey,
+                              Vector<uint8_t> &signature);
+    virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+    virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const;
+    virtual DrmStatus requiresSecureDecoder(const char *mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool *required) const;
+    virtual DrmStatus setPlaybackId(
             Vector<uint8_t> const &sessionId,
             const char *playbackId);
-    virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
-    virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+    virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+    virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const;
 
 private:
     sp<IDrm> mDrmHalHidl;
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
index 0f51ce9..a81b312 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalAidl.h
@@ -25,6 +25,7 @@
 #include <mediadrm/DrmMetrics.h>
 #include <mediadrm/DrmSessionManager.h>
 #include <mediadrm/DrmHalListener.h>
+#include <mediadrm/DrmStatus.h>
 #include <mediadrm/IDrm.h>
 
 using IDrmPluginAidl = ::aidl::android::hardware::drm::IDrmPlugin;
@@ -38,74 +39,78 @@
     struct DrmSessionClient;
     DrmHalAidl();
     virtual ~DrmHalAidl();
-    virtual status_t initCheck() const;
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
-                                             DrmPlugin::SecurityLevel securityLevel, bool* result);
-    virtual status_t createPlugin(const uint8_t uuid[16], const String8& appPackageName);
-    virtual status_t destroyPlugin();
-    virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
-                                 Vector<uint8_t>& sessionId);
-    virtual status_t closeSession(Vector<uint8_t> const& sessionId);
-    virtual status_t getKeyRequest(Vector<uint8_t> const& sessionId,
-                                   Vector<uint8_t> const& initData, String8 const& mimeType,
-                                   DrmPlugin::KeyType keyType,
-                                   KeyedVector<String8, String8> const& optionalParameters,
-                                   Vector<uint8_t>& request, String8& defaultUrl,
-                                   DrmPlugin::KeyRequestType* keyRequestType);
-    virtual status_t provideKeyResponse(Vector<uint8_t> const& sessionId,
-                                        Vector<uint8_t> const& response, Vector<uint8_t>& keySetId);
-    virtual status_t removeKeys(Vector<uint8_t> const& keySetId);
-    virtual status_t restoreKeys(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keySetId);
-    virtual status_t queryKeyStatus(Vector<uint8_t> const& sessionId,
-                                    KeyedVector<String8, String8>& infoMap) const;
-    virtual status_t getProvisionRequest(String8 const& certType, String8 const& certAuthority,
-                                         Vector<uint8_t>& request, String8& defaultUrl);
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const& response,
-                                              Vector<uint8_t>& certificate,
-                                              Vector<uint8_t>& wrappedKey);
-    virtual status_t getSecureStops(List<Vector<uint8_t>>& secureStops);
-    virtual status_t getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
-    virtual status_t getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
-    virtual status_t releaseSecureStops(Vector<uint8_t> const& ssRelease);
-    virtual status_t removeSecureStop(Vector<uint8_t> const& ssid);
-    virtual status_t removeAllSecureStops();
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
-                                   DrmPlugin::HdcpLevel* maxLevel) const;
-    virtual status_t getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
-    virtual status_t getSecurityLevel(Vector<uint8_t> const& sessionId,
-                                      DrmPlugin::SecurityLevel* level) const;
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const& keySetId);
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const& keySetId,
-                                            DrmPlugin::OfflineLicenseState* licenseState) const;
-    virtual status_t getPropertyString(String8 const& name, String8& value) const;
-    virtual status_t getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
-    virtual status_t setPropertyString(String8 const& name, String8 const& value) const;
-    virtual status_t setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
-    virtual status_t getMetrics(const sp<IDrmMetricsConsumer>& consumer);
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
-    virtual status_t encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                             Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                             Vector<uint8_t>& output);
-    virtual status_t decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                             Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
-                             Vector<uint8_t>& output);
-    virtual status_t sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                          Vector<uint8_t> const& message, Vector<uint8_t>& signature);
-    virtual status_t verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
-                            Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
-                            bool& match);
-    virtual status_t signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
-                             Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
-                             Vector<uint8_t>& signature);
-    virtual status_t setListener(const sp<IDrmClient>& listener);
-    virtual status_t requiresSecureDecoder(const char* mime, bool* required) const;
-    virtual status_t requiresSecureDecoder(const char* mime, DrmPlugin::SecurityLevel securityLevel,
-                                           bool* required) const;
-    virtual status_t setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
-    virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
-    virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+    virtual DrmStatus initCheck() const;
+    virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel securityLevel, bool* result);
+    virtual DrmStatus createPlugin(const uint8_t uuid[16], const String8& appPackageName);
+    virtual DrmStatus destroyPlugin();
+    virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
+                                  Vector<uint8_t>& sessionId);
+    virtual DrmStatus closeSession(Vector<uint8_t> const& sessionId);
+    virtual DrmStatus getKeyRequest(Vector<uint8_t> const& sessionId,
+                                    Vector<uint8_t> const& initData, String8 const& mimeType,
+                                    DrmPlugin::KeyType keyType,
+                                    KeyedVector<String8, String8> const& optionalParameters,
+                                    Vector<uint8_t>& request, String8& defaultUrl,
+                                    DrmPlugin::KeyRequestType* keyRequestType);
+    virtual DrmStatus provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                         Vector<uint8_t> const& response,
+                                         Vector<uint8_t>& keySetId);
+    virtual DrmStatus removeKeys(Vector<uint8_t> const& keySetId);
+    virtual DrmStatus restoreKeys(Vector<uint8_t> const& sessionId,
+                                  Vector<uint8_t> const& keySetId);
+    virtual DrmStatus queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                     KeyedVector<String8, String8>& infoMap) const;
+    virtual DrmStatus getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+                                          Vector<uint8_t>& request, String8& defaultUrl);
+    virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& certificate,
+                                               Vector<uint8_t>& wrappedKey);
+    virtual DrmStatus getSecureStops(List<Vector<uint8_t>>& secureStops);
+    virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+    virtual DrmStatus getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+    virtual DrmStatus releaseSecureStops(Vector<uint8_t> const& ssRelease);
+    virtual DrmStatus removeSecureStop(Vector<uint8_t> const& ssid);
+    virtual DrmStatus removeAllSecureStops();
+    virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+                                    DrmPlugin::HdcpLevel* maxLevel) const;
+    virtual DrmStatus getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+    virtual DrmStatus getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                       DrmPlugin::SecurityLevel* level) const;
+    virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+    virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const& keySetId);
+    virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+                                             DrmPlugin::OfflineLicenseState* licenseState) const;
+    virtual DrmStatus getPropertyString(String8 const& name, String8& value) const;
+    virtual DrmStatus getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+    virtual DrmStatus setPropertyString(String8 const& name, String8 const& value) const;
+    virtual DrmStatus setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+    virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+    virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                         String8 const& algorithm);
+    virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+    virtual DrmStatus encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output);
+    virtual DrmStatus decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output);
+    virtual DrmStatus sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                           Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+    virtual DrmStatus verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                             Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                             bool& match);
+    virtual DrmStatus signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                              Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+                              Vector<uint8_t>& signature);
+    virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+    virtual DrmStatus requiresSecureDecoder(const char* mime, bool* required) const;
+    virtual DrmStatus requiresSecureDecoder(const char* mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool* required) const;
+    virtual DrmStatus setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+    virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+    virtual DrmStatus getSupportedSchemes(std::vector<uint8_t>& schemes) const;
 
     ::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
                                  const std::vector<uint8_t>& in_sessionId,
@@ -118,7 +123,7 @@
     ::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
   private:
     static Mutex mLock;
-    mutable MediaDrmMetrics mMetrics;
+    std::shared_ptr<MediaDrmMetrics> mMetrics;
     std::shared_ptr<DrmHalListener> mListener;
     const std::vector<std::shared_ptr<IDrmFactoryAidl>> mFactories;
     std::shared_ptr<IDrmPluginAidl> mPlugin;
@@ -128,8 +133,8 @@
     void closeOpenSessions();
     std::string reportPluginMetrics() const;
     std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
-    status_t getPropertyStringInternal(String8 const& name, String8& value) const;
-    status_t getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
+    DrmStatus getPropertyStringInternal(String8 const& name, String8& value) const;
+    DrmStatus getPropertyByteArrayInternal(String8 const& name, Vector<uint8_t>& value) const;
     DISALLOW_EVIL_CONSTRUCTORS(DrmHalAidl);
 };
 
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
index 11f0608..73a9e1d 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalHidl.h
@@ -26,6 +26,7 @@
 #include <media/drm/DrmAPI.h>
 #include <mediadrm/DrmMetrics.h>
 #include <mediadrm/DrmSessionManager.h>
+#include <mediadrm/DrmStatus.h>
 #include <mediadrm/IDrm.h>
 #include <mediadrm/IDrmClient.h>
 #include <mediadrm/IDrmMetricsConsumer.h>
@@ -63,24 +64,22 @@
     DrmHalHidl();
     virtual ~DrmHalHidl();
 
-    virtual status_t initCheck() const;
+    virtual DrmStatus initCheck() const;
 
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
-                                             const String8& mimeType,
-                                             DrmPlugin::SecurityLevel level,
-                                             bool *isSupported);
+    virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel level, bool* isSupported);
 
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8 &appPackageName);
+    virtual DrmStatus createPlugin(const uint8_t uuid[16],
+                                   const String8 &appPackageName);
 
-    virtual status_t destroyPlugin();
+    virtual DrmStatus destroyPlugin();
 
-    virtual status_t openSession(DrmPlugin::SecurityLevel level,
+    virtual DrmStatus openSession(DrmPlugin::SecurityLevel level,
             Vector<uint8_t> &sessionId);
 
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId);
+    virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId);
 
-    virtual status_t
+    virtual DrmStatus
         getKeyRequest(Vector<uint8_t> const &sessionId,
                       Vector<uint8_t> const &initData,
                       String8 const &mimeType, DrmPlugin::KeyType keyType,
@@ -88,103 +87,104 @@
                       Vector<uint8_t> &request, String8 &defaultUrl,
                       DrmPlugin::KeyRequestType *keyRequestType);
 
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId);
+    virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                         Vector<uint8_t> const &response,
+                                         Vector<uint8_t> &keySetId);
 
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
+    virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId);
 
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId);
+    virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+                                  Vector<uint8_t> const &keySetId);
 
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                    KeyedVector<String8, String8> &infoMap) const;
+    virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+                                     KeyedVector<String8, String8> &infoMap) const;
 
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaultUrl);
+    virtual DrmStatus getProvisionRequest(String8 const &certType,
+                                          String8 const &certAuthority,
+                                          Vector<uint8_t> &request,
+                                          String8 &defaultUrl);
 
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey);
+    virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+                                               Vector<uint8_t> &certificate,
+                                               Vector<uint8_t> &wrappedKey);
 
-    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
-    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
+    virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops);
+    virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
+    virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
 
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
-    virtual status_t removeAllSecureStops();
+    virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease);
+    virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid);
+    virtual DrmStatus removeAllSecureStops();
 
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+    virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel) const;
-    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+    virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
             uint32_t *maxSessions) const;
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+    virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
             DrmPlugin::SecurityLevel *level) const;
 
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId);
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+    virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const;
+    virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId);
+    virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
             DrmPlugin::OfflineLicenseState *licenseState) const;
 
-    virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
-    virtual status_t getPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> &value ) const;
-    virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value ) const;
-    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer);
+    virtual DrmStatus getPropertyString(String8 const &name, String8 &value ) const;
+    virtual DrmStatus getPropertyByteArray(String8 const &name,
+                                           Vector<uint8_t> &value ) const;
+    virtual DrmStatus setPropertyString(String8 const &name, String8 const &value ) const;
+    virtual DrmStatus setPropertyByteArray(String8 const &name,
+                                           Vector<uint8_t> const &value ) const;
+    virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer);
 
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm);
+    virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                         String8 const &algorithm);
 
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm);
+    virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                      String8 const &algorithm);
 
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+    virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &keyId,
+                              Vector<uint8_t> const &input,
+                              Vector<uint8_t> const &iv,
+                              Vector<uint8_t> &output);
+
+    virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &keyId,
+                              Vector<uint8_t> const &input,
+                              Vector<uint8_t> const &iv,
+                              Vector<uint8_t> &output);
+
+    virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+                           Vector<uint8_t> const &keyId,
+                           Vector<uint8_t> const &message,
+                           Vector<uint8_t> &signature);
+
+    virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
                              Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output);
-
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output);
-
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature);
-
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match);
-
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
                              Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature);
+                             Vector<uint8_t> const &signature,
+                             bool &match);
 
-    virtual status_t setListener(const sp<IDrmClient>& listener);
+    virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+                              String8 const &algorithm,
+                              Vector<uint8_t> const &message,
+                              Vector<uint8_t> const &wrappedKey,
+                              Vector<uint8_t> &signature);
 
-    virtual status_t requiresSecureDecoder(const char *mime, bool *required) const;
+    virtual DrmStatus setListener(const sp<IDrmClient>& listener);
 
-    virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
-                                           bool *required) const;
+    virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const;
 
-    virtual status_t setPlaybackId(
+    virtual DrmStatus requiresSecureDecoder(const char *mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool *required) const;
+
+    virtual DrmStatus setPlaybackId(
             Vector<uint8_t> const &sessionId,
             const char *playbackId);
 
-    virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
-    virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const;
+    virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const;
+    virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const;
 
     // Methods of IDrmPluginListener
     Return<void> sendEvent(EventType eventType,
@@ -238,10 +238,10 @@
 
     std::string reportPluginMetrics() const;
     std::string reportFrameworkMetrics(const std::string& pluginMetrics) const;
-    status_t getPropertyStringInternal(String8 const &name, String8 &value) const;
-    status_t getPropertyByteArrayInternal(String8 const &name,
+    DrmStatus getPropertyStringInternal(String8 const &name, String8 &value) const;
+    DrmStatus getPropertyByteArrayInternal(String8 const &name,
                                           Vector<uint8_t> &value) const;
-    status_t matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
+    DrmStatus matchMimeTypeAndSecurityLevel(const sp<IDrmFactory> &factory,
                                            const uint8_t uuid[16],
                                            const String8 &mimeType,
                                            DrmPlugin::SecurityLevel level,
diff --git a/drm/libmediadrm/include/mediadrm/DrmHalListener.h b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
index 22361ad..0eed929 100644
--- a/drm/libmediadrm/include/mediadrm/DrmHalListener.h
+++ b/drm/libmediadrm/include/mediadrm/DrmHalListener.h
@@ -27,7 +27,7 @@
 
 namespace android {
 struct DrmHalListener : public BnDrmPluginListener {
-    explicit DrmHalListener(MediaDrmMetrics* mMetrics);
+    explicit DrmHalListener(const std::shared_ptr<MediaDrmMetrics>& in_metrics);
     ~DrmHalListener();
     ::ndk::ScopedAStatus onEvent(EventTypeAidl in_eventType,
                                  const std::vector<uint8_t>& in_sessionId,
@@ -38,9 +38,9 @@
                                       const std::vector<KeyStatusAidl>& in_keyStatusList,
                                       bool in_hasNewUsableKey);
     ::ndk::ScopedAStatus onSessionLostState(const std::vector<uint8_t>& in_sessionId);
-    void setListener(sp<IDrmClient> listener);
+    void setListener(const sp<IDrmClient>& listener);
 private:
-    mutable MediaDrmMetrics* mMetrics;
+    std::shared_ptr<MediaDrmMetrics> mMetrics;
     sp<IDrmClient> mListener;
     mutable Mutex mEventLock;
     mutable Mutex mNotifyLock;
diff --git a/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
new file mode 100644
index 0000000..7666f04
--- /dev/null
+++ b/drm/libmediadrm/include/mediadrm/DrmMetricsLogger.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mediadrm/DrmStatus.h>
+#include <mediadrm/IDrm.h>
+#include <sys/random.h>
+#include <map>
+#include <mutex>
+
+#ifndef DRM_METRICS_LOGGER_H
+#define DRM_METRICS_LOGGER_H
+
+namespace android {
+
+enum {
+    JERROR_DRM_UNKNOWN = 0,
+    JERROR_DRM_NO_LICENSE = 1,
+    JERROR_DRM_LICENSE_EXPIRED = 2,
+    JERROR_DRM_RESOURCE_BUSY = 3,
+    JERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = 4,
+    JERROR_DRM_SESSION_NOT_OPENED = 5,
+    JERROR_DRM_CANNOT_HANDLE = 6,
+    JERROR_DRM_INSUFFICIENT_SECURITY = 7,
+    JERROR_DRM_FRAME_TOO_LARGE = 8,
+    JERROR_DRM_SESSION_LOST_STATE = 9,
+    JERROR_DRM_CERTIFICATE_MALFORMED = 10,
+    JERROR_DRM_CERTIFICATE_MISSING = 11,
+    JERROR_DRM_CRYPTO_LIBRARY = 12,
+    JERROR_DRM_GENERIC_OEM = 13,
+    JERROR_DRM_GENERIC_PLUGIN = 14,
+    JERROR_DRM_INIT_DATA = 15,
+    JERROR_DRM_KEY_NOT_LOADED = 16,
+    JERROR_DRM_LICENSE_PARSE = 17,
+    JERROR_DRM_LICENSE_POLICY = 18,
+    JERROR_DRM_LICENSE_RELEASE = 19,
+    JERROR_DRM_LICENSE_REQUEST_REJECTED = 20,
+    JERROR_DRM_LICENSE_RESTORE = 21,
+    JERROR_DRM_LICENSE_STATE = 22,
+    JERROR_DRM_MEDIA_FRAMEWORK = 23,
+    JERROR_DRM_PROVISIONING_CERTIFICATE = 24,
+    JERROR_DRM_PROVISIONING_CONFIG = 25,
+    JERROR_DRM_PROVISIONING_PARSE = 26,
+    JERROR_DRM_PROVISIONING_REQUEST_REJECTED = 27,
+    JERROR_DRM_PROVISIONING_RETRY = 28,
+    JERROR_DRM_RESOURCE_CONTENTION = 29,
+    JERROR_DRM_SECURE_STOP_RELEASE = 30,
+    JERROR_DRM_STORAGE_READ = 31,
+    JERROR_DRM_STORAGE_WRITE = 32,
+    JERROR_DRM_ZERO_SUBSAMPLES = 33,
+};
+
+enum {
+    JSecurityLevelUnknown = 0,
+    JSecurityLevelSwSecureCrypto = 1,
+    JSecurityLevelSwSecureDecode = 2,
+    JSecurityLevelHwSecureCrypto = 3,
+    JSecurityLevelHwSecureDecode = 4,
+    JSecurityLevelHwSecureAll = 5,
+    JSecurityLevelMax = 6,
+};
+
+struct SessionContext {
+    std::string mNonce;
+    DrmPlugin::SecurityLevel mTargetSecurityLevel;
+    DrmPlugin::SecurityLevel mActualSecurityLevel;
+    std::string mVersion;
+};
+
+class DrmMetricsLogger : public IDrm {
+  public:
+    DrmMetricsLogger(IDrmFrontend);
+
+    virtual ~DrmMetricsLogger();
+
+    virtual DrmStatus initCheck() const;
+
+    virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[IDRM_UUID_SIZE],
+                                              const String8& mimeType,
+                                              DrmPlugin::SecurityLevel securityLevel,
+                                              bool* result);
+
+    virtual DrmStatus createPlugin(const uint8_t uuid[IDRM_UUID_SIZE],
+                                   const String8& appPackageName);
+
+    virtual DrmStatus destroyPlugin();
+
+    virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
+                                  Vector<uint8_t>& sessionId);
+
+    virtual DrmStatus closeSession(Vector<uint8_t> const& sessionId);
+
+    virtual DrmStatus getKeyRequest(Vector<uint8_t> const& sessionId,
+                                    Vector<uint8_t> const& initData, String8 const& mimeType,
+                                    DrmPlugin::KeyType keyType,
+                                    KeyedVector<String8, String8> const& optionalParameters,
+                                    Vector<uint8_t>& request, String8& defaultUrl,
+                                    DrmPlugin::KeyRequestType* keyRequestType);
+
+    virtual DrmStatus provideKeyResponse(Vector<uint8_t> const& sessionId,
+                                         Vector<uint8_t> const& response,
+                                         Vector<uint8_t>& keySetId);
+
+    virtual DrmStatus removeKeys(Vector<uint8_t> const& keySetId);
+
+    virtual DrmStatus restoreKeys(Vector<uint8_t> const& sessionId,
+                                  Vector<uint8_t> const& keySetId);
+
+    virtual DrmStatus queryKeyStatus(Vector<uint8_t> const& sessionId,
+                                     KeyedVector<String8, String8>& infoMap) const;
+
+    virtual DrmStatus getProvisionRequest(String8 const& certType, String8 const& certAuthority,
+                                          Vector<uint8_t>& request, String8& defaultUrl);
+
+    virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const& response,
+                                               Vector<uint8_t>& certificate,
+                                               Vector<uint8_t>& wrappedKey);
+
+    virtual DrmStatus getSecureStops(List<Vector<uint8_t>>& secureStops);
+    virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>>& secureStopIds);
+    virtual DrmStatus getSecureStop(Vector<uint8_t> const& ssid, Vector<uint8_t>& secureStop);
+
+    virtual DrmStatus releaseSecureStops(Vector<uint8_t> const& ssRelease);
+    virtual DrmStatus removeSecureStop(Vector<uint8_t> const& ssid);
+    virtual DrmStatus removeAllSecureStops();
+
+    virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel* connectedLevel,
+                                    DrmPlugin::HdcpLevel* maxLevel) const;
+    virtual DrmStatus getNumberOfSessions(uint32_t* currentSessions, uint32_t* maxSessions) const;
+    virtual DrmStatus getSecurityLevel(Vector<uint8_t> const& sessionId,
+                                       DrmPlugin::SecurityLevel* level) const;
+
+    virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>>& keySetIds) const;
+    virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const& keySetId);
+    virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const& keySetId,
+                                             DrmPlugin::OfflineLicenseState* licenseState) const;
+
+    virtual DrmStatus getPropertyString(String8 const& name, String8& value) const;
+    virtual DrmStatus getPropertyByteArray(String8 const& name, Vector<uint8_t>& value) const;
+    virtual DrmStatus setPropertyString(String8 const& name, String8 const& value) const;
+    virtual DrmStatus setPropertyByteArray(String8 const& name, Vector<uint8_t> const& value) const;
+
+    virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer>& consumer);
+
+    virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const& sessionId,
+                                         String8 const& algorithm);
+
+    virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const& sessionId, String8 const& algorithm);
+
+    virtual DrmStatus encrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output);
+
+    virtual DrmStatus decrypt(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                              Vector<uint8_t> const& input, Vector<uint8_t> const& iv,
+                              Vector<uint8_t>& output);
+
+    virtual DrmStatus sign(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                           Vector<uint8_t> const& message, Vector<uint8_t>& signature);
+
+    virtual DrmStatus verify(Vector<uint8_t> const& sessionId, Vector<uint8_t> const& keyId,
+                             Vector<uint8_t> const& message, Vector<uint8_t> const& signature,
+                             bool& match);
+
+    virtual DrmStatus signRSA(Vector<uint8_t> const& sessionId, String8 const& algorithm,
+                              Vector<uint8_t> const& message, Vector<uint8_t> const& wrappedKey,
+                              Vector<uint8_t>& signature);
+
+    virtual DrmStatus setListener(const sp<IDrmClient>& listener);
+
+    virtual DrmStatus requiresSecureDecoder(const char* mime, bool* required) const;
+
+    virtual DrmStatus requiresSecureDecoder(const char* mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool* required) const;
+
+    virtual DrmStatus setPlaybackId(Vector<uint8_t> const& sessionId, const char* playbackId);
+
+    virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage>& logs) const;
+
+    virtual DrmStatus getSupportedSchemes(std::vector<uint8_t>& schemes) const;
+
+    void reportMediaDrmCreated() const;
+
+    void reportMediaDrmSessionOpened(const std::vector<uint8_t>& sessionId) const;
+
+    void reportMediaDrmErrored(
+            const DrmStatus& error_code, const char* api,
+            const std::vector<uint8_t>& sessionId = std::vector<uint8_t>()) const;
+
+    DrmStatus generateNonce(std::string* out, size_t size, const char* api);
+
+  private:
+    static const size_t kNonceSize = 16;
+    static const std::map<std::array<int64_t, 2>, std::string> kUuidSchemeMap;
+    sp<IDrm> mImpl;
+    std::array<int64_t, 2> mUuid;
+    std::string mObjNonce;
+    std::string mScheme;
+    std::string mVersion;
+    std::map<std::vector<uint8_t>, SessionContext> mSessionMap;
+    mutable std::mutex mSessionMapMutex;
+    IDrmFrontend mFrontend;
+    DISALLOW_EVIL_CONSTRUCTORS(DrmMetricsLogger);
+};
+
+}  // namespace android
+
+#endif  // DRM_METRICS_LOGGER_H
\ No newline at end of file
diff --git a/drm/libmediadrm/include/mediadrm/IDrm.h b/drm/libmediadrm/include/mediadrm/IDrm.h
index ee2be6a..ff5f63b 100644
--- a/drm/libmediadrm/include/mediadrm/IDrm.h
+++ b/drm/libmediadrm/include/mediadrm/IDrm.h
@@ -16,6 +16,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/drm/DrmAPI.h>
+#include <mediadrm/DrmStatus.h>
 #include <mediadrm/IDrmClient.h>
 #include <mediadrm/IDrmMetricsConsumer.h>
 
@@ -23,6 +24,8 @@
 
 #define ANDROID_IDRM_H_
 
+#define IDRM_UUID_SIZE (16)
+
 namespace android {
 namespace hardware {
 namespace drm {
@@ -32,6 +35,13 @@
 }  // namespace drm
 }  // namespace hardware
 
+enum IDrmFrontend : int32_t {
+    IDRM_UNKNOWN = 0,
+    IDRM_JNI = 1,
+    IDRM_NDK = 2,
+    IDRM_NUPLAYER = 3,
+};
+
 namespace drm = ::android::hardware::drm;
 
 struct AString;
@@ -40,24 +50,23 @@
 
     virtual ~IDrm() {}
 
-    virtual status_t initCheck() const = 0;
+    virtual DrmStatus initCheck() const = 0;
 
-    virtual status_t isCryptoSchemeSupported(const uint8_t uuid[16],
-                                             const String8 &mimeType,
-                                             DrmPlugin::SecurityLevel securityLevel,
-                                             bool *result) = 0;
+    virtual DrmStatus isCryptoSchemeSupported(const uint8_t uuid[16], const String8& mimeType,
+                                              DrmPlugin::SecurityLevel securityLevel,
+                                              bool* result) = 0;
 
-    virtual status_t createPlugin(const uint8_t uuid[16],
-                                  const String8 &appPackageName) = 0;
+    virtual DrmStatus createPlugin(const uint8_t uuid[16],
+                                   const String8 &appPackageName) = 0;
 
-    virtual status_t destroyPlugin() = 0;
+    virtual DrmStatus destroyPlugin() = 0;
 
-    virtual status_t openSession(DrmPlugin::SecurityLevel securityLevel,
+    virtual DrmStatus openSession(DrmPlugin::SecurityLevel securityLevel,
             Vector<uint8_t> &sessionId) = 0;
 
-    virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0;
+    virtual DrmStatus closeSession(Vector<uint8_t> const &sessionId) = 0;
 
-    virtual status_t
+    virtual DrmStatus
         getKeyRequest(Vector<uint8_t> const &sessionId,
                       Vector<uint8_t> const &initData,
                       String8 const &mimeType, DrmPlugin::KeyType keyType,
@@ -65,107 +74,108 @@
                       Vector<uint8_t> &request, String8 &defaultUrl,
                       DrmPlugin::KeyRequestType *keyRequestType) = 0;
 
-    virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
-                                        Vector<uint8_t> const &response,
-                                        Vector<uint8_t> &keySetId) = 0;
+    virtual DrmStatus provideKeyResponse(Vector<uint8_t> const &sessionId,
+                                         Vector<uint8_t> const &response,
+                                         Vector<uint8_t> &keySetId) = 0;
 
-    virtual status_t removeKeys(Vector<uint8_t> const &keySetId) = 0;
+    virtual DrmStatus removeKeys(Vector<uint8_t> const &keySetId) = 0;
 
-    virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
-                                 Vector<uint8_t> const &keySetId) = 0;
+    virtual DrmStatus restoreKeys(Vector<uint8_t> const &sessionId,
+                                  Vector<uint8_t> const &keySetId) = 0;
 
-    virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
-                                    KeyedVector<String8, String8> &infoMap) const = 0;
+    virtual DrmStatus queryKeyStatus(Vector<uint8_t> const &sessionId,
+                                     KeyedVector<String8, String8> &infoMap) const = 0;
 
-    virtual status_t getProvisionRequest(String8 const &certType,
-                                         String8 const &certAuthority,
-                                         Vector<uint8_t> &request,
-                                         String8 &defaulUrl) = 0;
+    virtual DrmStatus getProvisionRequest(String8 const &certType,
+                                          String8 const &certAuthority,
+                                          Vector<uint8_t> &request,
+                                          String8 &defaultUrl) = 0;
 
-    virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
-                                              Vector<uint8_t> &certificate,
-                                              Vector<uint8_t> &wrappedKey) = 0;
+    virtual DrmStatus provideProvisionResponse(Vector<uint8_t> const &response,
+                                               Vector<uint8_t> &certificate,
+                                               Vector<uint8_t> &wrappedKey) = 0;
 
-    virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
-    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
-    virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
+    virtual DrmStatus getSecureStops(List<Vector<uint8_t>> &secureStops) = 0;
+    virtual DrmStatus getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) = 0;
+    virtual DrmStatus getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
 
-    virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
-    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
-    virtual status_t removeAllSecureStops() = 0;
+    virtual DrmStatus releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
+    virtual DrmStatus removeSecureStop(Vector<uint8_t> const &ssid) = 0;
+    virtual DrmStatus removeAllSecureStops() = 0;
 
-    virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
+    virtual DrmStatus getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel)
             const = 0;
-    virtual status_t getNumberOfSessions(uint32_t *currentSessions,
+    virtual DrmStatus getNumberOfSessions(uint32_t *currentSessions,
             uint32_t *maxSessions) const = 0;
-    virtual status_t getSecurityLevel(Vector<uint8_t> const &sessionId,
+    virtual DrmStatus getSecurityLevel(Vector<uint8_t> const &sessionId,
             DrmPlugin::SecurityLevel *level) const = 0;
 
-    virtual status_t getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
-    virtual status_t removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
-    virtual status_t getOfflineLicenseState(Vector<uint8_t> const &keySetId,
+    virtual DrmStatus getOfflineLicenseKeySetIds(List<Vector<uint8_t>> &keySetIds) const = 0;
+    virtual DrmStatus removeOfflineLicense(Vector<uint8_t> const &keySetId) = 0;
+    virtual DrmStatus getOfflineLicenseState(Vector<uint8_t> const &keySetId,
             DrmPlugin::OfflineLicenseState *licenseState) const = 0;
 
-    virtual status_t getPropertyString(String8 const &name, String8 &value) const = 0;
-    virtual status_t getPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> &value) const = 0;
-    virtual status_t setPropertyString(String8 const &name,
-                                       String8 const &value ) const = 0;
-    virtual status_t setPropertyByteArray(String8 const &name,
-                                          Vector<uint8_t> const &value) const = 0;
+    virtual DrmStatus getPropertyString(String8 const &name, String8 &value) const = 0;
+    virtual DrmStatus getPropertyByteArray(String8 const &name,
+                                           Vector<uint8_t> &value) const = 0;
+    virtual DrmStatus setPropertyString(String8 const &name,
+                                        String8 const &value ) const = 0;
+    virtual DrmStatus setPropertyByteArray(String8 const &name,
+                                           Vector<uint8_t> const &value) const = 0;
 
-    virtual status_t getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
+    virtual DrmStatus getMetrics(const sp<IDrmMetricsConsumer> &consumer) = 0;
 
-    virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
-                                        String8 const &algorithm) = 0;
+    virtual DrmStatus setCipherAlgorithm(Vector<uint8_t> const &sessionId,
+                                         String8 const &algorithm) = 0;
 
-    virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
-                                     String8 const &algorithm) = 0;
+    virtual DrmStatus setMacAlgorithm(Vector<uint8_t> const &sessionId,
+                                      String8 const &algorithm) = 0;
 
-    virtual status_t encrypt(Vector<uint8_t> const &sessionId,
+    virtual DrmStatus encrypt(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &keyId,
+                              Vector<uint8_t> const &input,
+                              Vector<uint8_t> const &iv,
+                              Vector<uint8_t> &output) = 0;
+
+    virtual DrmStatus decrypt(Vector<uint8_t> const &sessionId,
+                              Vector<uint8_t> const &keyId,
+                              Vector<uint8_t> const &input,
+                              Vector<uint8_t> const &iv,
+                              Vector<uint8_t> &output) = 0;
+
+    virtual DrmStatus sign(Vector<uint8_t> const &sessionId,
+                           Vector<uint8_t> const &keyId,
+                           Vector<uint8_t> const &message,
+                           Vector<uint8_t> &signature) = 0;
+
+    virtual DrmStatus verify(Vector<uint8_t> const &sessionId,
                              Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) = 0;
-
-    virtual status_t decrypt(Vector<uint8_t> const &sessionId,
-                             Vector<uint8_t> const &keyId,
-                             Vector<uint8_t> const &input,
-                             Vector<uint8_t> const &iv,
-                             Vector<uint8_t> &output) = 0;
-
-    virtual status_t sign(Vector<uint8_t> const &sessionId,
-                          Vector<uint8_t> const &keyId,
-                          Vector<uint8_t> const &message,
-                          Vector<uint8_t> &signature) = 0;
-
-    virtual status_t verify(Vector<uint8_t> const &sessionId,
-                            Vector<uint8_t> const &keyId,
-                            Vector<uint8_t> const &message,
-                            Vector<uint8_t> const &signature,
-                            bool &match) = 0;
-
-    virtual status_t signRSA(Vector<uint8_t> const &sessionId,
-                             String8 const &algorithm,
                              Vector<uint8_t> const &message,
-                             Vector<uint8_t> const &wrappedKey,
-                             Vector<uint8_t> &signature) = 0;
+                             Vector<uint8_t> const &signature,
+                             bool &match) = 0;
 
-    virtual status_t setListener(const sp<IDrmClient>& listener) = 0;
+    virtual DrmStatus signRSA(Vector<uint8_t> const &sessionId,
+                              String8 const &algorithm,
+                              Vector<uint8_t> const &message,
+                              Vector<uint8_t> const &wrappedKey,
+                              Vector<uint8_t> &signature) = 0;
 
-    virtual status_t requiresSecureDecoder(const char *mime, bool *required) const = 0;
+    virtual DrmStatus setListener(const sp<IDrmClient>& listener) = 0;
 
-    virtual status_t requiresSecureDecoder(const char *mime, DrmPlugin::SecurityLevel securityLevel,
-                                           bool *required) const = 0;
+    virtual DrmStatus requiresSecureDecoder(const char *mime, bool *required) const = 0;
 
-    virtual status_t setPlaybackId(
+    virtual DrmStatus requiresSecureDecoder(const char *mime,
+                                            DrmPlugin::SecurityLevel securityLevel,
+                                            bool *required) const = 0;
+
+    virtual DrmStatus setPlaybackId(
             Vector<uint8_t> const &sessionId,
             const char *playbackId) = 0;
 
-    virtual status_t getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
+    virtual DrmStatus getLogMessages(Vector<drm::V1_4::LogMessage> &logs) const = 0;
 
-    virtual status_t getSupportedSchemes(std::vector<uint8_t> &schemes) const = 0;
+    virtual DrmStatus getSupportedSchemes(std::vector<uint8_t> &schemes) const = 0;
 
 protected:
     IDrm() {}
diff --git a/drm/libmediadrm/interface/mediadrm/DrmStatus.h b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
new file mode 100644
index 0000000..15826ca
--- /dev/null
+++ b/drm/libmediadrm/interface/mediadrm/DrmStatus.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_STATUS_
+#define DRM_STATUS_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+
+#include <stdint.h>
+#include <string>
+
+namespace android {
+
+struct DrmStatus {
+  public:
+    DrmStatus(status_t status, int32_t cdmErr = 0, int32_t oemErr = 0,
+              int32_t ctx = 0, std::string errMsg = "")
+        : mStatus(status), mCdmErr(cdmErr), mOemErr(oemErr),
+          mCtx(ctx), mErrMsg(errMsg) {}
+    DrmStatus(status_t err, const char *msg);
+    operator status_t() const { return mStatus; }
+    int32_t getCdmErr() const { return mCdmErr; }
+    int32_t getOemErr() const { return mOemErr; }
+    int32_t getContext() const { return mCtx; }
+    std::string getErrorMessage() const { return mErrMsg; }
+    bool operator==(status_t other) const { return mStatus == other; }
+    bool operator!=(status_t other) const { return mStatus != other; }
+
+  private:
+    status_t mStatus{};
+    int32_t mCdmErr{}, mOemErr{}, mCtx{};
+    std::string mErrMsg;
+};
+
+}  // namespace android
+
+#endif  // DRM_STATUS_
diff --git a/drm/libmediadrm/interface/mediadrm/DrmUtils.h b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
index 980ce55..ba20b95 100644
--- a/drm/libmediadrm/interface/mediadrm/DrmUtils.h
+++ b/drm/libmediadrm/interface/mediadrm/DrmUtils.h
@@ -22,6 +22,8 @@
 #include <android/hardware/drm/1.4/IDrmPlugin.h>
 #include <android/hardware/drm/1.4/types.h>
 #include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmMetricsLogger.h>
+#include <mediadrm/DrmStatus.h>
 #include <utils/Errors.h>  // for status_t
 #include <utils/Log.h>
 #include <utils/String8.h>
@@ -35,6 +37,7 @@
 #include <ctime>
 #include <deque>
 #include <endian.h>
+#include <inttypes.h>
 #include <iterator>
 #include <mutex>
 #include <string>
@@ -103,9 +106,9 @@
 void LogToBuffer(android_LogPriority level, const uint8_t uuid[16], const char *fmt, Args... args) {
     uint64_t uuid2[2] = {};
     std::memcpy(uuid2, uuid, sizeof(uuid2));
-    std::string uuidFmt("uuid=[%lx %lx] ");
+    std::string uuidFmt("uuid=[%" PRIx64 " %" PRIx64 "] ");
     uuidFmt += fmt;
-    LogToBuffer(level, uuidFmt.c_str(), htobe64(uuid2[0]), htobe64(uuid2[1]), args...);
+    LogToBuffer(level, uuidFmt.c_str(), betoh64(uuid2[0]), betoh64(uuid2[1]), args...);
 }
 
 #ifndef LOG2BE
@@ -118,7 +121,7 @@
 
 bool UseDrmService();
 
-sp<IDrm> MakeDrm(status_t *pstatus = nullptr);
+sp<IDrm> MakeDrm(IDrmFrontend frontend = IDRM_JNI, status_t* pstatus = nullptr);
 
 sp<ICrypto> MakeCrypto(status_t *pstatus = nullptr);
 
@@ -198,98 +201,7 @@
     return toStatusT_1_4(err);
 }
 
-inline status_t statusAidlToStatusT(::ndk::ScopedAStatus &statusAidl) {
-    if (statusAidl.isOk()) return OK;
-    if (statusAidl.getExceptionCode() != EX_SERVICE_SPECIFIC) return DEAD_OBJECT;
-    auto status = static_cast<StatusAidl>(statusAidl.getServiceSpecificError());
-    switch (status) {
-    case StatusAidl::OK:
-        return OK;
-    case StatusAidl::BAD_VALUE:
-        return BAD_VALUE;
-    case StatusAidl::ERROR_DRM_CANNOT_HANDLE:
-        return ERROR_DRM_CANNOT_HANDLE;
-    case StatusAidl::ERROR_DRM_DECRYPT:
-        return ERROR_DRM_DECRYPT;
-    case StatusAidl::ERROR_DRM_DEVICE_REVOKED:
-        return ERROR_DRM_DEVICE_REVOKED;
-    case StatusAidl::ERROR_DRM_FRAME_TOO_LARGE:
-        return ERROR_DRM_FRAME_TOO_LARGE;
-    case StatusAidl::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
-        return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
-    case StatusAidl::ERROR_DRM_INSUFFICIENT_SECURITY:
-        return ERROR_DRM_INSUFFICIENT_SECURITY;
-    case StatusAidl::ERROR_DRM_INVALID_STATE:
-        return ERROR_DRM_INVALID_STATE;
-    case StatusAidl::ERROR_DRM_LICENSE_EXPIRED:
-        return ERROR_DRM_LICENSE_EXPIRED;
-    case StatusAidl::ERROR_DRM_NO_LICENSE:
-        return ERROR_DRM_NO_LICENSE;
-    case StatusAidl::ERROR_DRM_NOT_PROVISIONED:
-        return ERROR_DRM_NOT_PROVISIONED;
-    case StatusAidl::ERROR_DRM_RESOURCE_BUSY:
-        return ERROR_DRM_RESOURCE_BUSY;
-    case StatusAidl::ERROR_DRM_RESOURCE_CONTENTION:
-        return ERROR_DRM_RESOURCE_CONTENTION;
-    case StatusAidl::ERROR_DRM_SESSION_LOST_STATE:
-        return ERROR_DRM_SESSION_LOST_STATE;
-    case StatusAidl::ERROR_DRM_SESSION_NOT_OPENED:
-        return ERROR_DRM_SESSION_NOT_OPENED;
-
-    // New in S / drm@1.4:
-    case StatusAidl::CANNOT_DECRYPT_ZERO_SUBSAMPLES:
-        return ERROR_DRM_ZERO_SUBSAMPLES;
-    case StatusAidl::CRYPTO_LIBRARY_ERROR:
-        return ERROR_DRM_CRYPTO_LIBRARY;
-    case StatusAidl::GENERAL_OEM_ERROR:
-        return ERROR_DRM_GENERIC_OEM;
-    case StatusAidl::GENERAL_PLUGIN_ERROR:
-        return ERROR_DRM_GENERIC_PLUGIN;
-    case StatusAidl::INIT_DATA_INVALID:
-        return ERROR_DRM_INIT_DATA;
-    case StatusAidl::KEY_NOT_LOADED:
-        return ERROR_DRM_KEY_NOT_LOADED;
-    case StatusAidl::LICENSE_PARSE_ERROR:
-        return ERROR_DRM_LICENSE_PARSE;
-    case StatusAidl::LICENSE_POLICY_ERROR:
-        return ERROR_DRM_LICENSE_POLICY;
-    case StatusAidl::LICENSE_RELEASE_ERROR:
-        return ERROR_DRM_LICENSE_RELEASE;
-    case StatusAidl::LICENSE_REQUEST_REJECTED:
-        return ERROR_DRM_LICENSE_REQUEST_REJECTED;
-    case StatusAidl::LICENSE_RESTORE_ERROR:
-        return ERROR_DRM_LICENSE_RESTORE;
-    case StatusAidl::LICENSE_STATE_ERROR:
-        return ERROR_DRM_LICENSE_STATE;
-    case StatusAidl::MALFORMED_CERTIFICATE:
-        return ERROR_DRM_CERTIFICATE_MALFORMED;
-    case StatusAidl::MEDIA_FRAMEWORK_ERROR:
-        return ERROR_DRM_MEDIA_FRAMEWORK;
-    case StatusAidl::MISSING_CERTIFICATE:
-        return ERROR_DRM_CERTIFICATE_MISSING;
-    case StatusAidl::PROVISIONING_CERTIFICATE_ERROR:
-        return ERROR_DRM_PROVISIONING_CERTIFICATE;
-    case StatusAidl::PROVISIONING_CONFIGURATION_ERROR:
-        return ERROR_DRM_PROVISIONING_CONFIG;
-    case StatusAidl::PROVISIONING_PARSE_ERROR:
-        return ERROR_DRM_PROVISIONING_PARSE;
-    case StatusAidl::PROVISIONING_REQUEST_REJECTED:
-        return ERROR_DRM_PROVISIONING_REQUEST_REJECTED;
-    case StatusAidl::RETRYABLE_PROVISIONING_ERROR:
-        return ERROR_DRM_PROVISIONING_RETRY;
-    case StatusAidl::SECURE_STOP_RELEASE_ERROR:
-        return ERROR_DRM_SECURE_STOP_RELEASE;
-    case StatusAidl::STORAGE_READ_FAILURE:
-        return ERROR_DRM_STORAGE_READ;
-    case StatusAidl::STORAGE_WRITE_FAILURE:
-        return ERROR_DRM_STORAGE_WRITE;
-
-    case StatusAidl::ERROR_DRM_UNKNOWN:
-    default:
-        return ERROR_DRM_UNKNOWN;
-    }
-    return ERROR_DRM_UNKNOWN;
-}
+DrmStatus statusAidlToDrmStatus(::ndk::ScopedAStatus& statusAidl);
 
 template<typename T, typename U>
 status_t GetLogMessagesAidl(const std::shared_ptr<U> &obj, Vector<::V1_4::LogMessage> &logs) {
@@ -373,14 +285,16 @@
     return OK;
 }
 
-std::string GetExceptionMessage(status_t err, const char *msg,
+std::string GetExceptionMessage(const DrmStatus & err, const char *defaultMsg,
                                 const Vector<::V1_4::LogMessage> &logs);
 
 template<typename T>
-std::string GetExceptionMessage(status_t err, const char *msg, const sp<T> &iface) {
+std::string GetExceptionMessage(const DrmStatus &err, const char *defaultMsg, const sp<T> &iface) {
     Vector<::V1_4::LogMessage> logs;
-    iface->getLogMessages(logs);
-    return GetExceptionMessage(err, msg, logs);
+    if (iface != NULL) {
+        iface->getLogMessages(logs);
+    }
+    return GetExceptionMessage(err, defaultMsg, logs);
 }
 
 } // namespace DrmUtils
diff --git a/drm/libmediadrm/interface/mediadrm/ICrypto.h b/drm/libmediadrm/interface/mediadrm/ICrypto.h
index 2c4df60..4087186 100644
--- a/drm/libmediadrm/interface/mediadrm/ICrypto.h
+++ b/drm/libmediadrm/interface/mediadrm/ICrypto.h
@@ -17,6 +17,7 @@
 #include <cutils/native_handle.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/ABase.h>
+#include <mediadrm/DrmStatus.h>
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
 
@@ -65,7 +66,7 @@
 
     virtual void notifyResolution(uint32_t width, uint32_t height) = 0;
 
-    virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
+    virtual DrmStatus setMediaDrmSession(const Vector<uint8_t> &sessionId) = 0;
 
     enum DestinationType {
         kDestinationTypeSharedMemory, // non-secure
diff --git a/drm/mediadrm/plugins/clearkey/aidl/Android.bp b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
index 2d1f741..eaf5051 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/aidl/Android.bp
@@ -37,6 +37,7 @@
     static_libs: [
         "android.hardware.common-V2-ndk",
         "libclearkeybase",
+        "libjsoncpp",
     ],
 
     local_include_dirs: ["include"],
@@ -69,3 +70,56 @@
         "android.hardware.drm-service.clearkey",
     ],
 }
+
+cc_defaults {
+    name: "fuzz_aidl_clearkey_service_defaults",
+
+    srcs: [
+        "CreatePluginFactories.cpp",
+        "CryptoPlugin.cpp",
+        "DrmFactory.cpp",
+        "DrmPlugin.cpp",
+    ],
+
+    relative_install_path: "hw",
+
+    cflags: ["-Wall", "-Werror", "-Wthread-safety"],
+
+    include_dirs: ["frameworks/av/include"],
+
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcrypto",
+        "liblog",
+        "libprotobuf-cpp-lite",
+        "libutils",
+        "android.hardware.drm-V1-ndk",
+    ],
+
+    static_libs: [
+        "android.hardware.common-V2-ndk",
+        "libclearkeybase_fuzz",
+        "libjsoncpp",
+    ],
+
+    local_include_dirs: ["include"],
+
+    sanitize: {
+        integer_overflow: true,
+    },
+}
+
+cc_fuzz {
+    name: "android.hardware.drm-service.clearkey.aidl_fuzzer",
+    defaults: [
+        "fuzz_aidl_clearkey_service_defaults",
+        "service_fuzzer_defaults",
+    ],
+    srcs: ["fuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "hamzeh@google.com",
+        ],
+    },
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
index afc9b6a..a63471f 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/CryptoPlugin.cpp
@@ -137,6 +137,8 @@
         *_aidl_return = static_cast<ssize_t>(offset);
         return toNdkScopedAStatus(Status::OK);
     } else if (in_args.mode == Mode::AES_CTR) {
+        if (!mSession) return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE,
+                    "session not found");
         size_t bytesDecrypted{};
         std::vector<int32_t> clearDataLengths;
         std::vector<int32_t> encryptedDataLengths;
@@ -149,6 +151,7 @@
             detailedError = "invalid decrypt parameter size";
             return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
         }
+
         auto res =
                 mSession->decrypt(in_args.keyId.data(), in_args.iv.data(),
                                   srcPtr, static_cast<uint8_t*>(destPtr),
diff --git a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
index ea51e9d..e8dec80 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/aidl/DrmPlugin.cpp
@@ -16,6 +16,7 @@
 #define LOG_TAG "clearkey-DrmPlugin"
 
 #include <aidl/android/hardware/drm/DrmMetric.h>
+#include <android-base/parseint.h>
 #include <utils/Log.h>
 
 #include <inttypes.h>
@@ -83,12 +84,14 @@
 void DrmPlugin::initProperties() {
     mStringProperties.clear();
     mStringProperties[kVendorKey] = kAidlVendorValue;
-    mStringProperties[kVersionKey] = kAidlVersionValue;
+    mStringProperties[kVersionKey] = kVersionValue;
     mStringProperties[kPluginDescriptionKey] = kAidlPluginDescriptionValue;
     mStringProperties[kAlgorithmsKey] = kAidlAlgorithmsValue;
     mStringProperties[kListenerTestSupportKey] = kAidlListenerTestSupportValue;
     mStringProperties[kDrmErrorTestKey] = kAidlDrmErrorTestValue;
     mStringProperties[kAidlVersionKey] = kAidlVersionValue;
+    mStringProperties[kOemErrorKey] = "0";
+    mStringProperties[kErrorContextKey] = "0";
 
     std::vector<uint8_t> valueVector;
     valueVector.clear();
@@ -102,6 +105,26 @@
     mByteArrayProperties[kMetricsKey] = valueVector;
 }
 
+int32_t DrmPlugin::getIntProperty(const std::string& prop, int32_t defaultVal) const {
+    if (!mStringProperties.count(prop)) {
+        return defaultVal;
+    }
+    int32_t out = defaultVal;
+    if (!::android::base::ParseInt(mStringProperties.at(prop), &out)) {
+        return defaultVal;
+    }
+    return out;
+}
+
+int32_t DrmPlugin::getOemError() const {
+    return getIntProperty(kOemErrorKey);
+}
+
+int32_t DrmPlugin::getErrorContext() const {
+    return getIntProperty(kErrorContextKey);
+}
+
+//
 // The secure stop in ClearKey implementation is not installed securely.
 // This function merely creates a test environment for testing secure stops APIs.
 // The content in this secure stop is implementation dependent, the clearkey
@@ -127,7 +150,10 @@
         mSessionLibrary->destroySession(session);
         if (session->getMockError() != clearkeydrm::OK) {
             sendSessionLostState(in_sessionId);
-            return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE);
+            return toNdkScopedAStatus(Status::ERROR_DRM_INVALID_STATE,
+                                      nullptr,
+                                      getOemError(),
+                                      getErrorContext());
         }
         mCloseSessionOkCount++;
         return toNdkScopedAStatus(Status::OK);
@@ -198,7 +224,8 @@
         if (!session.get()) {
             return toNdkScopedAStatus(Status::ERROR_DRM_SESSION_NOT_OPENED);
         } else if (session->getMockError() != clearkeydrm::OK) {
-            return toNdkScopedAStatus(session->getMockError());
+            auto err = static_cast<Status>(session->getMockError());
+            return toNdkScopedAStatus(err, nullptr, getOemError(), getErrorContext());
         }
         keyRequestType = KeyRequestType::INITIAL;
     }
@@ -381,6 +408,10 @@
         value = mStringProperties[kDrmErrorTestKey];
     } else if (name == kAidlVersionKey) {
         value = mStringProperties[kAidlVersionKey];
+    } else if (name == kOemErrorKey) {
+        value = mStringProperties[kOemErrorKey];
+    } else if (name == kErrorContextKey) {
+        value = mStringProperties[kErrorContextKey];
     } else {
         ALOGE("App requested unknown string property %s", name.c_str());
         status = Status::ERROR_DRM_CANNOT_HANDLE;
@@ -920,6 +951,13 @@
         }
     }
 
+    if (in_propertyName == kOemErrorKey || in_propertyName == kErrorContextKey) {
+        int32_t err = 0;
+        if (!::android::base::ParseInt(in_value, &err)) {
+            return toNdkScopedAStatus(Status::BAD_VALUE);
+        }
+    }
+
     mStringProperties[key] = std::string(in_value.c_str());
     return toNdkScopedAStatus(Status::OK);
 }
diff --git a/drm/mediadrm/plugins/clearkey/aidl/fuzzer.cpp b/drm/mediadrm/plugins/clearkey/aidl/fuzzer.cpp
new file mode 100644
index 0000000..9ef331f
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/aidl/fuzzer.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "CreatePluginFactories.h"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::aidl::android::hardware::drm::clearkey::createDrmFactory;
+using ::aidl::android::hardware::drm::clearkey::DrmFactory;
+
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    std::shared_ptr<DrmFactory> drmFactory = createDrmFactory();
+    fuzzService(drmFactory->asBinder().get(),  FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
index 9257b17..0db3c37 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/AidlUtils.h
@@ -15,9 +15,12 @@
  */
 #pragma once
 
+#include <cstdint>
 #include <string>
 #include <vector>
 
+#include <json/json.h>
+
 #include <android/binder_auto_utils.h>
 #include "aidl/android/hardware/drm/Status.h"
 #include "ClearKeyTypes.h"
@@ -41,17 +44,32 @@
 }
 
 inline ::ndk::ScopedAStatus toNdkScopedAStatus(::aidl::android::hardware::drm::Status status,
-                                               const char* msg = nullptr) {
+                                               const char* msg = nullptr,
+                                               int32_t oemError = 0,
+                                               int32_t errorContext = 0) {
+
+
     if (Status::OK == status) {
         return ::ndk::ScopedAStatus::ok();
-    } else {
-        auto err = static_cast<int32_t>(status);
-        if (msg) {
-            return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(err, msg);
-        } else {
-            return ::ndk::ScopedAStatus::fromServiceSpecificError(err);
-        }
     }
+
+    Json::Value errObj(Json::objectValue);
+    auto err = static_cast<int32_t>(status);
+    errObj["cdmError"] = err;
+
+    if (oemError) {
+        errObj["oemError"] = oemError;
+    }
+    if (errorContext) {
+        errObj["context"] = errorContext;
+    }
+    if (msg) {
+        errObj["errorMessage"] = msg;
+    }
+
+    Json::FastWriter writer;
+    return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+        err, writer.write(errObj).c_str());
 }
 
 inline ::ndk::ScopedAStatus toNdkScopedAStatus(clearkeydrm::CdmResponseType res) {
diff --git a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
index 25c05f0..ea85ac8 100644
--- a/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/aidl/include/DrmPlugin.h
@@ -148,6 +148,9 @@
 
   private:
     void initProperties();
+    int32_t getIntProperty(const std::string& prop, int32_t defaultVal = 0) const;
+    int32_t getOemError() const;
+    int32_t getErrorContext() const;
     void installSecureStop(const std::vector<uint8_t>& sessionId);
     bool makeKeySetId(std::string* keySetId);
     void setPlayPolicy();
diff --git a/drm/mediadrm/plugins/clearkey/common/Android.bp b/drm/mediadrm/plugins/clearkey/common/Android.bp
index a6a5b28..6913df4 100644
--- a/drm/mediadrm/plugins/clearkey/common/Android.bp
+++ b/drm/mediadrm/plugins/clearkey/common/Android.bp
@@ -97,3 +97,54 @@
         integer_overflow: true,
     },
 }
+
+cc_library_static {
+    name: "libclearkeydevicefiles-protos.common_fuzz",
+
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    srcs: ["protos/DeviceFiles.proto"],
+}
+
+cc_library_static {
+    name: "libclearkeybase_fuzz",
+
+    srcs: [
+        "AesCtrDecryptor.cpp",
+        "Base64.cpp",
+        "Buffer.cpp",
+        "ClearKeyUUID.cpp",
+        "DeviceFiles.cpp",
+        "InitDataParser.cpp",
+        "JsonWebKey.cpp",
+        "MemoryFileSystem.cpp",
+        "Session.cpp",
+        "SessionLibrary.cpp",
+        "Utils.cpp",
+    ],
+
+    cflags: ["-Wall", "-Werror"],
+
+    include_dirs: ["frameworks/av/include"],
+
+    shared_libs: [
+        "libutils",
+        "libcrypto",
+    ],
+
+    whole_static_libs: [
+        "libjsmn",
+        "libclearkeydevicefiles-protos.common_fuzz",
+    ],
+
+    export_include_dirs: [
+        "include",
+        "include/clearkeydrm",
+    ],
+
+    sanitize: {
+        integer_overflow: true,
+    },
+}
diff --git a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
index bfda388..d4e641e 100644
--- a/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
+++ b/drm/mediadrm/plugins/clearkey/common/include/clearkeydrm/ClearKeyDrmProperties.h
@@ -21,7 +21,7 @@
 static const std::string kVendorKey("vendor");
 static const std::string kVendorValue("Google");
 static const std::string kVersionKey("version");
-static const std::string kVersionValue("1.2");
+static const std::string kVersionValue("14"); // sync with Android OS version
 static const std::string kPluginDescriptionKey("description");
 static const std::string kPluginDescriptionValue("ClearKey CDM");
 static const std::string kAlgorithmsKey("algorithms");
@@ -35,6 +35,8 @@
 static const std::string kFrameTooLargeValue("frameTooLarge");
 static const std::string kInvalidStateValue("invalidState");
 static const std::string kAidlVersionKey("aidlVersion");
+static const std::string kOemErrorKey("oemError");
+static const std::string kErrorContextKey("errorContext");
 
 static const std::string kDeviceIdKey("deviceId");
 static const uint8_t kTestDeviceIdData[] = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
diff --git a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
index 7bc320d..64a43b0 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/CryptoPlugin.cpp
@@ -211,6 +211,10 @@
             _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid decrypt parameter size");
             return Void();
         }
+        if (!mSession) {
+            _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "session not found");
+            return Void();
+        }
         Status_V1_2 res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
                 static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
         if (res == Status_V1_2::OK) {
diff --git a/include/media/MicrophoneInfo.h b/include/media/MicrophoneInfo.h
deleted file mode 100644
index a5045b9..0000000
--- a/include/media/MicrophoneInfo.h
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef ANDROID_MICROPHONE_INFO_H
-#define ANDROID_MICROPHONE_INFO_H
-
-#include <android/media/MicrophoneInfoData.h>
-#include <binder/Parcel.h>
-#include <binder/Parcelable.h>
-#include <media/AidlConversionUtil.h>
-#include <system/audio.h>
-
-namespace android {
-namespace media {
-
-class MicrophoneInfo : public Parcelable {
-public:
-    MicrophoneInfo() = default;
-    MicrophoneInfo(const MicrophoneInfo& microphoneInfo) = default;
-    MicrophoneInfo(audio_microphone_characteristic_t& characteristic) {
-        mDeviceId = std::string(&characteristic.device_id[0]);
-        mPortId = characteristic.id;
-        mType = characteristic.device;
-        mAddress = std::string(&characteristic.address[0]);
-        mDeviceLocation = characteristic.location;
-        mDeviceGroup = characteristic.group;
-        mIndexInTheGroup = characteristic.index_in_the_group;
-        mGeometricLocation.push_back(characteristic.geometric_location.x);
-        mGeometricLocation.push_back(characteristic.geometric_location.y);
-        mGeometricLocation.push_back(characteristic.geometric_location.z);
-        mOrientation.push_back(characteristic.orientation.x);
-        mOrientation.push_back(characteristic.orientation.y);
-        mOrientation.push_back(characteristic.orientation.z);
-        std::vector<float> frequencies;
-        std::vector<float> responses;
-        for (size_t i = 0; i < characteristic.num_frequency_responses; i++) {
-            frequencies.push_back(characteristic.frequency_responses[0][i]);
-            responses.push_back(characteristic.frequency_responses[1][i]);
-        }
-        mFrequencyResponses.push_back(frequencies);
-        mFrequencyResponses.push_back(responses);
-        for (size_t i = 0; i < AUDIO_CHANNEL_COUNT_MAX; i++) {
-            mChannelMapping.push_back(characteristic.channel_mapping[i]);
-        }
-        mSensitivity = characteristic.sensitivity;
-        mMaxSpl = characteristic.max_spl;
-        mMinSpl = characteristic.min_spl;
-        mDirectionality = characteristic.directionality;
-    }
-
-    virtual ~MicrophoneInfo() = default;
-
-    virtual status_t writeToParcel(Parcel* parcel) const {
-        MicrophoneInfoData parcelable;
-        return writeToParcelable(&parcelable)
-               ?: parcelable.writeToParcel(parcel);
-    }
-
-    virtual status_t writeToParcelable(MicrophoneInfoData* parcelable) const {
-        parcelable->deviceId = mDeviceId;
-        parcelable->portId = mPortId;
-        parcelable->type = VALUE_OR_RETURN_STATUS(convertReinterpret<int32_t>(mType));
-        parcelable->address = mAddress;
-        parcelable->deviceGroup = mDeviceGroup;
-        parcelable->indexInTheGroup = mIndexInTheGroup;
-        parcelable->geometricLocation = mGeometricLocation;
-        parcelable->orientation = mOrientation;
-        if (mFrequencyResponses.size() != 2) {
-            return BAD_VALUE;
-        }
-        parcelable->frequencies = mFrequencyResponses[0];
-        parcelable->frequencyResponses = mFrequencyResponses[1];
-        parcelable->channelMapping = mChannelMapping;
-        parcelable->sensitivity = mSensitivity;
-        parcelable->maxSpl = mMaxSpl;
-        parcelable->minSpl = mMinSpl;
-        parcelable->directionality = mDirectionality;
-        return OK;
-    }
-
-    virtual status_t readFromParcel(const Parcel* parcel) {
-        MicrophoneInfoData data;
-        return data.readFromParcel(parcel)
-            ?: readFromParcelable(data);
-    }
-
-    virtual status_t readFromParcelable(const MicrophoneInfoData& parcelable) {
-        mDeviceId = parcelable.deviceId;
-        mPortId = parcelable.portId;
-        mType = VALUE_OR_RETURN_STATUS(convertReinterpret<uint32_t>(parcelable.type));
-        mAddress = parcelable.address;
-        mDeviceLocation = parcelable.deviceLocation;
-        mDeviceGroup = parcelable.deviceGroup;
-        mIndexInTheGroup = parcelable.indexInTheGroup;
-        if (parcelable.geometricLocation.size() != 3) {
-            return BAD_VALUE;
-        }
-        mGeometricLocation = parcelable.geometricLocation;
-        if (parcelable.orientation.size() != 3) {
-            return BAD_VALUE;
-        }
-        mOrientation = parcelable.orientation;
-        if (parcelable.frequencies.size() != parcelable.frequencyResponses.size()) {
-            return BAD_VALUE;
-        }
-
-        mFrequencyResponses.push_back(parcelable.frequencies);
-        mFrequencyResponses.push_back(parcelable.frequencyResponses);
-        if (parcelable.channelMapping.size() != AUDIO_CHANNEL_COUNT_MAX) {
-            return BAD_VALUE;
-        }
-        mChannelMapping = parcelable.channelMapping;
-        mSensitivity = parcelable.sensitivity;
-        mMaxSpl = parcelable.maxSpl;
-        mMinSpl = parcelable.minSpl;
-        mDirectionality = parcelable.directionality;
-        return OK;
-    }
-
-    std::string getDeviceId() const {
-        return mDeviceId;
-    }
-
-    int getPortId() const {
-        return mPortId;
-    }
-
-    unsigned int getType() const {
-        return mType;
-    }
-
-    std::string getAddress() const {
-        return mAddress;
-    }
-
-    int getDeviceLocation() const {
-        return mDeviceLocation;
-    }
-
-    int getDeviceGroup() const {
-        return mDeviceGroup;
-    }
-
-    int getIndexInTheGroup() const {
-        return mIndexInTheGroup;
-    }
-
-    const std::vector<float>& getGeometricLocation() const {
-        return mGeometricLocation;
-    }
-
-    const std::vector<float>& getOrientation() const {
-        return mOrientation;
-    }
-
-    const std::vector<std::vector<float>>& getFrequencyResponses() const {
-        return mFrequencyResponses;
-    }
-
-    const std::vector<int>& getChannelMapping() const {
-        return mChannelMapping;
-    }
-
-    float getSensitivity() const {
-        return mSensitivity;
-    }
-
-    float getMaxSpl() const {
-        return mMaxSpl;
-    }
-
-    float getMinSpl() const {
-        return mMinSpl;
-    }
-
-    int getDirectionality() const {
-        return mDirectionality;
-    }
-
-private:
-    std::string mDeviceId;
-    int32_t mPortId;
-    uint32_t mType;
-    std::string mAddress;
-    int32_t mDeviceLocation;
-    int32_t mDeviceGroup;
-    int32_t mIndexInTheGroup;
-    std::vector<float> mGeometricLocation;
-    std::vector<float> mOrientation;
-    std::vector<std::vector<float>> mFrequencyResponses;
-    std::vector<int> mChannelMapping;
-    float mSensitivity;
-    float mMaxSpl;
-    float mMinSpl;
-    int32_t mDirectionality;
-};
-
-// Conversion routines, according to AidlConversion.h conventions.
-inline ConversionResult<MicrophoneInfo>
-aidl2legacy_MicrophoneInfo(const media::MicrophoneInfoData& aidl) {
-    MicrophoneInfo legacy;
-    RETURN_IF_ERROR(legacy.readFromParcelable(aidl));
-    return legacy;
-}
-
-inline ConversionResult<media::MicrophoneInfoData>
-legacy2aidl_MicrophoneInfo(const MicrophoneInfo& legacy) {
-    media::MicrophoneInfoData aidl;
-    RETURN_IF_ERROR(legacy.writeToParcelable(&aidl));
-    return aidl;
-}
-
-} // namespace media
-} // namespace android
-
-#endif
diff --git a/media/TEST_MAPPING b/media/TEST_MAPPING
index 048301f..9aa896c 100644
--- a/media/TEST_MAPPING
+++ b/media/TEST_MAPPING
@@ -1,7 +1,24 @@
 // for frameworks/av/media
 {
-    // TODO (b/229286407) Add EncodeDecodeTest and DecodeEditEncodeTest to
-    // presubmit-large once issues in cuttlefish are fixed
+    "presubmit-large": [
+        // runs whenever we change something in this tree
+        {
+            "name": "CtsMediaCodecTestCases",
+            "options": [
+                {
+                    "include-filter": "android.media.codec.cts.EncodeDecodeTest"
+                }
+            ]
+        },
+        {
+            "name": "CtsMediaCodecTestCases",
+            "options": [
+                {
+                    "include-filter": "android.media.codec.cts.DecodeEditEncodeTest"
+                }
+            ]
+        }
+    ],
     "presubmit": [
         {
             "name": "GtsMediaTestCases",
@@ -15,13 +32,17 @@
                 {
                     "include-filter": "com.google.android.media.gts.WidevineH264PlaybackTests"
                 }
-            ]
-        }
-    ],
-
-    "imports": [
+            ],
+            "file_patterns": ["(?i)drm|crypto"]
+        },
         {
-            "path": "frameworks/av/drm/mediadrm/plugins"
+            "name": "CtsMediaDrmFrameworkTestCases",
+            "options" : [
+                {
+                    "include-annotation": "android.platform.test.annotations.Presubmit"
+                }
+            ],
+            "file_patterns": ["(?i)drm|crypto"]
         }
     ],
 
diff --git a/media/audioaidlconversion/AidlConversionCppNdk.cpp b/media/audioaidlconversion/AidlConversionCppNdk.cpp
new file mode 100644
index 0000000..8c2b940
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionCppNdk.cpp
@@ -0,0 +1,3014 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <map>
+#include <utility>
+#include <vector>
+
+#define LOG_TAG "AidlConversionCppNdk"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include "media/AidlConversionCppNdk.h"
+
+#include <media/ShmemCompat.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL CPP/NDK backend to legacy audio data structure conversion utilities.
+
+#if defined(BACKEND_NDK)
+/* AIDL String generated in NDK is different than CPP */
+#define GET_DEVICE_DESC_CONNECTION(x)  AudioDeviceDescription::CONNECTION_##x
+namespace aidl {
+#else
+#define GET_DEVICE_DESC_CONNECTION(x)  AudioDeviceDescription::CONNECTION_##x()
+#endif
+
+namespace android {
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::String16;
+using ::android::String8;
+using ::android::status_t;
+using ::android::base::unexpected;
+
+using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioConfig;
+using media::audio::common::AudioConfigBase;
+using media::audio::common::AudioContentType;
+using media::audio::common::AudioDevice;
+using media::audio::common::AudioDeviceAddress;
+using media::audio::common::AudioDeviceDescription;
+using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioDualMonoMode;
+using media::audio::common::AudioEncapsulationMetadataType;
+using media::audio::common::AudioEncapsulationMode;
+using media::audio::common::AudioEncapsulationType;
+using media::audio::common::AudioFormatDescription;
+using media::audio::common::AudioFormatType;
+using media::audio::common::AudioGain;
+using media::audio::common::AudioGainConfig;
+using media::audio::common::AudioGainMode;
+using media::audio::common::AudioInputFlags;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioLatencyMode;
+using media::audio::common::AudioMode;
+using media::audio::common::AudioOffloadInfo;
+using media::audio::common::AudioOutputFlags;
+using media::audio::common::AudioPlaybackRate;
+using media::audio::common::AudioPort;
+using media::audio::common::AudioPortConfig;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioPortExt;
+using media::audio::common::AudioPortMixExt;
+using media::audio::common::AudioPortMixExtUseCase;
+using media::audio::common::AudioProfile;
+using media::audio::common::AudioSource;
+using media::audio::common::AudioStandard;
+using media::audio::common::AudioStreamType;
+using media::audio::common::AudioUsage;
+using media::audio::common::AudioUuid;
+using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
+using media::audio::common::MicrophoneDynamicInfo;
+using media::audio::common::MicrophoneInfo;
+using media::audio::common::PcmType;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
+    if (aidl.size() > maxSize - 1) {
+        return BAD_VALUE;
+    }
+    aidl.copy(dest, aidl.size());
+    dest[aidl.size()] = '\0';
+    return OK;
+}
+
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
+    if (legacy == nullptr) {
+        return unexpected(BAD_VALUE);
+    }
+    if (strnlen(legacy, maxSize) == maxSize) {
+        // No null-terminator.
+        return unexpected(BAD_VALUE);
+    }
+    return std::string(legacy);
+}
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_module_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_io_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_port_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
+    return convertReinterpret<audio_patch_handle_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
+    return convertReinterpret<audio_unique_id_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
+    return convertReinterpret<audio_hw_sync_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
+    return convertReinterpret<pid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
+    return convertReinterpret<uid_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
+    return String16(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
+    return std::string(String8(legacy).c_str());
+}
+
+// TODO b/182392769: create an optional -> optional util
+ConversionResult<std::optional<String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
+    if (!aidl.has_value()) {
+        return std::nullopt;
+    }
+    ConversionResult<String16> conversion =
+        VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
+    return conversion.value();
+}
+
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
+  if (!legacy.has_value()) {
+    return std::nullopt;
+  }
+  ConversionResult<std::string> conversion =
+      VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
+  return conversion.value();
+}
+
+ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
+    return String8(aidl.data(), aidl.size());
+}
+
+ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
+    return std::string(legacy.c_str());
+}
+
+namespace {
+
+namespace detail {
+using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
+using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
+using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
+using AudioChannelPairs = std::vector<AudioChannelPair>;
+using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
+using AudioDevicePairs = std::vector<AudioDevicePair>;
+using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
+using AudioFormatPairs = std::vector<AudioFormatPair>;
+}
+
+const detail::AudioChannelBitPairs& getInAudioChannelBits() {
+    static const detail::AudioChannelBitPairs pairs = {
+        { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
+        { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
+        // AUDIO_CHANNEL_IN_FRONT is at the end
+        { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
+        // AUDIO_CHANNEL_IN_*_PROCESSED not supported
+        // AUDIO_CHANNEL_IN_PRESSURE not supported
+        // AUDIO_CHANNEL_IN_*_AXIS not supported
+        // AUDIO_CHANNEL_IN_VOICE_* not supported
+        { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
+        { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
+        { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
+        { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
+        { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
+        { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
+        // When going from aidl to legacy, IN_CENTER is used
+        { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
+    };
+    return pairs;
+}
+
+const detail::AudioChannelPairs& getInAudioChannelPairs() {
+    static const detail::AudioChannelPairs pairs = {
+#define DEFINE_INPUT_LAYOUT(n)                                                 \
+            {                                                                  \
+                AUDIO_CHANNEL_IN_##n,                                          \
+                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+                        AudioChannelLayout::LAYOUT_##n)                        \
+            }
+
+        DEFINE_INPUT_LAYOUT(MONO),
+        DEFINE_INPUT_LAYOUT(STEREO),
+        DEFINE_INPUT_LAYOUT(FRONT_BACK),
+        // AUDIO_CHANNEL_IN_6 not supported
+        DEFINE_INPUT_LAYOUT(2POINT0POINT2),
+        DEFINE_INPUT_LAYOUT(2POINT1POINT2),
+        DEFINE_INPUT_LAYOUT(3POINT0POINT2),
+        DEFINE_INPUT_LAYOUT(3POINT1POINT2),
+        DEFINE_INPUT_LAYOUT(5POINT1)
+#undef DEFINE_INPUT_LAYOUT
+    };
+    return pairs;
+}
+
+const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
+    static const detail::AudioChannelBitPairs pairs = {
+#define DEFINE_OUTPUT_BITS(n)                                                  \
+            { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
+
+        DEFINE_OUTPUT_BITS(FRONT_LEFT),
+        DEFINE_OUTPUT_BITS(FRONT_RIGHT),
+        DEFINE_OUTPUT_BITS(FRONT_CENTER),
+        DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
+        DEFINE_OUTPUT_BITS(BACK_LEFT),
+        DEFINE_OUTPUT_BITS(BACK_RIGHT),
+        DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
+        DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
+        DEFINE_OUTPUT_BITS(BACK_CENTER),
+        DEFINE_OUTPUT_BITS(SIDE_LEFT),
+        DEFINE_OUTPUT_BITS(SIDE_RIGHT),
+        DEFINE_OUTPUT_BITS(TOP_CENTER),
+        DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
+        DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
+        DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
+        DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
+        DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
+        DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
+        DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
+        DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
+        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
+        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
+        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
+        DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
+        DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
+        DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
+#undef DEFINE_OUTPUT_BITS
+        { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
+        { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
+    };
+    return pairs;
+}
+
+const detail::AudioChannelPairs& getOutAudioChannelPairs() {
+    static const detail::AudioChannelPairs pairs = {
+#define DEFINE_OUTPUT_LAYOUT(n)                                                \
+            {                                                                  \
+                AUDIO_CHANNEL_OUT_##n,                                         \
+                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
+                        AudioChannelLayout::LAYOUT_##n)                        \
+            }
+
+        DEFINE_OUTPUT_LAYOUT(MONO),
+        DEFINE_OUTPUT_LAYOUT(STEREO),
+        DEFINE_OUTPUT_LAYOUT(2POINT1),
+        DEFINE_OUTPUT_LAYOUT(TRI),
+        DEFINE_OUTPUT_LAYOUT(TRI_BACK),
+        DEFINE_OUTPUT_LAYOUT(3POINT1),
+        DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
+        DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
+        DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(QUAD),
+        DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
+        DEFINE_OUTPUT_LAYOUT(SURROUND),
+        DEFINE_OUTPUT_LAYOUT(PENTA),
+        DEFINE_OUTPUT_LAYOUT(5POINT1),
+        DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
+        DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
+        DEFINE_OUTPUT_LAYOUT(6POINT1),
+        DEFINE_OUTPUT_LAYOUT(7POINT1),
+        DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
+        DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
+        DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
+        DEFINE_OUTPUT_LAYOUT(22POINT2),
+        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
+        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
+        DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
+        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
+        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
+#undef DEFINE_OUTPUT_LAYOUT
+    };
+    return pairs;
+}
+
+const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
+    static const detail::AudioChannelPairs pairs = {
+#define DEFINE_VOICE_LAYOUT(n)                                                 \
+            {                                                                  \
+                AUDIO_CHANNEL_IN_VOICE_##n,                                    \
+                AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>(  \
+                        AudioChannelLayout::VOICE_##n)                         \
+            }
+        DEFINE_VOICE_LAYOUT(UPLINK_MONO),
+        DEFINE_VOICE_LAYOUT(DNLINK_MONO),
+        DEFINE_VOICE_LAYOUT(CALL_MONO)
+#undef DEFINE_VOICE_LAYOUT
+    };
+    return pairs;
+}
+
+AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
+        const std::string& connection = "") {
+    AudioDeviceDescription result;
+    result.type = type;
+    result.connection = connection;
+    return result;
+}
+
+void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
+        audio_devices_t inputType, audio_devices_t outputType,
+        AudioDeviceType inType, AudioDeviceType outType,
+        const std::string& connection = "") {
+    pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
+    pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
+}
+
+const detail::AudioDevicePairs& getAudioDevicePairs() {
+    static const detail::AudioDevicePairs pairs = []() {
+        detail::AudioDevicePairs pairs = {{
+            {
+                AUDIO_DEVICE_NONE, AudioDeviceDescription{}
+            },
+            {
+                AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER_EARPIECE)
+            },
+            {
+                AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER)
+            },
+            {
+                AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_HEADPHONE,
+                        GET_DEVICE_DESC_CONNECTION(ANALOG))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_DEVICE,
+                        GET_DEVICE_DESC_CONNECTION(BT_SCO))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_CARKIT,
+                        GET_DEVICE_DESC_CONNECTION(BT_SCO))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_HEADPHONE,
+                        GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER,
+                        GET_DEVICE_DESC_CONNECTION(BT_A2DP))
+            },
+            {
+                AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_TELEPHONY_TX)
+            },
+            {
+                AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_LINE_AUX)
+            },
+            {
+                AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER_SAFE)
+            },
+            {
+                AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_HEARING_AID,
+                        GET_DEVICE_DESC_CONNECTION(WIRELESS))
+            },
+            {
+                AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_ECHO_CANCELLER)
+            },
+            {
+                AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SPEAKER,
+                        GET_DEVICE_DESC_CONNECTION(BT_LE))
+            },
+            {
+                AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_BROADCAST,
+                        GET_DEVICE_DESC_CONNECTION(BT_LE))
+            },
+            // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
+            {
+                AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_MICROPHONE)
+            },
+            {
+                AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_MICROPHONE_BACK)
+            },
+            {
+                AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_TELEPHONY_RX)
+            },
+            {
+                AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_TV_TUNER)
+            },
+            {
+                AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_LOOPBACK)
+            },
+            {
+                AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_DEVICE,
+                        GET_DEVICE_DESC_CONNECTION(BT_LE))
+            },
+            {
+                AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
+                        AudioDeviceType::IN_ECHO_REFERENCE)
+            },
+            {
+                AUDIO_DEVICE_IN_REMOTE_SUBMIX, make_AudioDeviceDescription(
+                         AudioDeviceType::IN_SUBMIX)
+            },
+            {
+                AUDIO_DEVICE_OUT_REMOTE_SUBMIX, make_AudioDeviceDescription(
+                        AudioDeviceType::OUT_SUBMIX,
+                        GET_DEVICE_DESC_CONNECTION(VIRTUAL))
+            }
+        }};
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
+                AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(ANALOG));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(BT_SCO));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(HDMI));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
+                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+                GET_DEVICE_DESC_CONNECTION(ANALOG));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
+                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
+                AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
+                AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(ANALOG));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(SPDIF));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(BT_A2DP));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(IP_V4));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(BUS));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
+                AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(USB));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(HDMI_ARC));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
+                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
+                GET_DEVICE_DESC_CONNECTION(HDMI_EARC));
+        append_AudioDeviceDescription(pairs,
+                AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
+                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
+                GET_DEVICE_DESC_CONNECTION(BT_LE));
+        return pairs;
+    }();
+#undef GET_DEVICE_DESC_CONNECTION
+    return pairs;
+}
+
+AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
+    AudioFormatDescription result;
+    result.type = type;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
+    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
+    result.pcm = pcm;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
+    AudioFormatDescription result;
+    result.encoding = encoding;
+    return result;
+}
+
+AudioFormatDescription make_AudioFormatDescription(PcmType transport,
+        const std::string& encoding) {
+    auto result = make_AudioFormatDescription(encoding);
+    result.pcm = transport;
+    return result;
+}
+
+const detail::AudioFormatPairs& getAudioFormatPairs() {
+    static const detail::AudioFormatPairs pairs = {{
+            {AUDIO_FORMAT_INVALID,
+             make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)},
+            {AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}},
+            {AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)},
+            {AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)},
+            {AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)},
+            {AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)},
+            {AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)},
+            {AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)},
+            {AUDIO_FORMAT_MP3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG)},
+            {AUDIO_FORMAT_AMR_NB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_NB)},
+            {AUDIO_FORMAT_AMR_WB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB)},
+            {AUDIO_FORMAT_AAC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MP4)},
+            {AUDIO_FORMAT_AAC_MAIN,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_MAIN)},
+            {AUDIO_FORMAT_AAC_LC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LC)},
+            {AUDIO_FORMAT_AAC_SSR,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SSR)},
+            {AUDIO_FORMAT_AAC_LTP,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LTP)},
+            {AUDIO_FORMAT_AAC_HE_V1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)},
+            {AUDIO_FORMAT_AAC_SCALABLE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)},
+            {AUDIO_FORMAT_AAC_ERLC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ERLC)},
+            {AUDIO_FORMAT_AAC_LD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LD)},
+            {AUDIO_FORMAT_AAC_HE_V2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)},
+            {AUDIO_FORMAT_AAC_ELD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ELD)},
+            {AUDIO_FORMAT_AAC_XHE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_XHE)
+
+            },
+            // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
+            // ago.
+            {AUDIO_FORMAT_VORBIS,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_VORBIS)},
+            {AUDIO_FORMAT_OPUS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_OPUS)},
+            {AUDIO_FORMAT_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC3)},
+            {AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3)},
+            {AUDIO_FORMAT_E_AC3_JOC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EAC3_JOC)},
+            {AUDIO_FORMAT_DTS, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS)},
+            {AUDIO_FORMAT_DTS_HD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD)},
+            {AUDIO_FORMAT_DTS_HD_MA,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_HD_MA)},
+            {AUDIO_FORMAT_DTS_UHD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1)},
+            {AUDIO_FORMAT_DTS_UHD_P2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2)},
+            // In the future, we would like to represent encapsulated bitstreams as
+            // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
+            // specify the format of the encapsulated bitstream.
+            {AUDIO_FORMAT_IEC61937,
+             make_AudioFormatDescription(PcmType::INT_16_BIT,
+                                         ::android::MEDIA_MIMETYPE_AUDIO_IEC61937)},
+            {AUDIO_FORMAT_DOLBY_TRUEHD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)},
+            {AUDIO_FORMAT_EVRC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRC)},
+            {AUDIO_FORMAT_EVRCB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCB)},
+            {AUDIO_FORMAT_EVRCWB,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCWB)},
+            {AUDIO_FORMAT_EVRCNW,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_EVRCNW)},
+            {AUDIO_FORMAT_AAC_ADIF,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADIF)},
+            {AUDIO_FORMAT_WMA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_WMA)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")},
+            {AUDIO_FORMAT_AMR_WB_PLUS,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)},
+            {AUDIO_FORMAT_MP2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)},
+            {AUDIO_FORMAT_QCELP,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_QCELP)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")},
+            {AUDIO_FORMAT_FLAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_FLAC)},
+            {AUDIO_FORMAT_ALAC, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_ALAC)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")},
+            {AUDIO_FORMAT_AAC_ADTS,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS)},
+            {AUDIO_FORMAT_AAC_ADTS_MAIN,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)},
+            {AUDIO_FORMAT_AAC_ADTS_LC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)},
+            {AUDIO_FORMAT_AAC_ADTS_SSR,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)},
+            {AUDIO_FORMAT_AAC_ADTS_LTP,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)},
+            {AUDIO_FORMAT_AAC_ADTS_HE_V1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)},
+            {AUDIO_FORMAT_AAC_ADTS_SCALABLE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)},
+            {AUDIO_FORMAT_AAC_ADTS_ERLC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)},
+            {AUDIO_FORMAT_AAC_ADTS_LD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)},
+            {AUDIO_FORMAT_AAC_ADTS_HE_V2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)},
+            {AUDIO_FORMAT_AAC_ADTS_ELD,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)},
+            {AUDIO_FORMAT_AAC_ADTS_XHE,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)},
+            {// Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
+             AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")},
+            {AUDIO_FORMAT_APTX, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_APTX)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")},
+            {AUDIO_FORMAT_AC4, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AC4)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")},
+            {AUDIO_FORMAT_MAT,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_MAT_1_0,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+                                         std::string(".1.0"))},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_MAT_2_0,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+                                         std::string(".2.0"))},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_MAT_2_1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DOLBY_MAT +
+                                         std::string(".2.1"))},
+            {AUDIO_FORMAT_AAC_LATM,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC)},
+            {AUDIO_FORMAT_AAC_LATM_LC,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)},
+            {AUDIO_FORMAT_AAC_LATM_HE_V1,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)},
+            {AUDIO_FORMAT_AAC_LATM_HE_V2,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_ADAPTIVE,
+             make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")},
+            {AUDIO_FORMAT_MPEGH,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)},
+            {AUDIO_FORMAT_MPEGH_BL_L3,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)},
+            {AUDIO_FORMAT_MPEGH_BL_L4,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)},
+            {AUDIO_FORMAT_MPEGH_LC_L3,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)},
+            {AUDIO_FORMAT_MPEGH_LC_L4,
+             make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)},
+            {AUDIO_FORMAT_IEC60958,
+             make_AudioFormatDescription(PcmType::INT_24_BIT,
+                                         ::android::MEDIA_MIMETYPE_AUDIO_IEC60958)},
+            {AUDIO_FORMAT_DRA, make_AudioFormatDescription(::android::MEDIA_MIMETYPE_AUDIO_DRA)},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_ADAPTIVE_QLEA,
+             make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r3")},
+            {// Note: not in the IANA registry.
+             AUDIO_FORMAT_APTX_ADAPTIVE_R4,
+             make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive.r4")},
+    }};
+    return pairs;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
+    std::map<S, T> result(v.begin(), v.end());
+    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+    return result;
+}
+
+template<typename S, typename T>
+std::map<S, T> make_DirectMap(
+        const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
+    std::map<S, T> result(v1.begin(), v1.end());
+    LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
+    result.insert(v2.begin(), v2.end());
+    LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
+            "Duplicate key elements detected in v1+v2");
+    return result;
+}
+
+template<typename S, typename T>
+std::map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
+    std::map<T, S> result;
+    std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
+            [](const std::pair<S, T>& p) {
+                return std::make_pair(p.second, p.first);
+            });
+    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
+    return result;
+}
+
+}  // namespace
+
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+        int aidlLayout, bool isInput) {
+    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+    const int aidlLayoutInitial = aidlLayout; // for error message
+    audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
+    for (const auto& bitPair : bitMapping) {
+        if ((aidlLayout & bitPair.second) == bitPair.second) {
+            legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
+            aidlLayout &= ~bitPair.second;
+            if (aidlLayout == 0) {
+                return legacy;
+            }
+        }
+    }
+    ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
+            __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
+    return AUDIO_CHANNEL_NONE;
+}
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+        const AudioChannelLayout& aidl, bool isInput) {
+    using ReverseMap = std::map<AudioChannelLayout, audio_channel_mask_t>;
+    using Tag = AudioChannelLayout::Tag;
+    static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
+    static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
+    static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
+
+    auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
+            const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
+        if (auto it = m.find(aidl); it != m.end()) {
+            return it->second;
+        } else {
+            ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
+                    aidl.toString().c_str());
+            return unexpected(BAD_VALUE);
+        }
+    };
+
+    switch (aidl.getTag()) {
+        case Tag::none:
+            return AUDIO_CHANNEL_NONE;
+        case Tag::invalid:
+            return AUDIO_CHANNEL_INVALID;
+        case Tag::indexMask:
+            // Index masks do not have pre-defined values.
+            if (const int bits = aidl.get<Tag::indexMask>();
+                __builtin_popcount(bits) != 0 &&
+                __builtin_popcount(bits) <= (int)AUDIO_CHANNEL_COUNT_MAX) {
+                return audio_channel_mask_from_representation_and_bits(
+                        AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
+            } else {
+                ALOGE("%s: invalid indexMask value 0x%x in %s",
+                        __func__, bits, aidl.toString().c_str());
+                return unexpected(BAD_VALUE);
+            }
+        case Tag::layoutMask:
+            // The fast path is to find a direct match for some known layout mask.
+            if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
+                    isInput ? "input" : "output");
+                    layoutMatch.ok()) {
+                return layoutMatch;
+            }
+            // If a match for a predefined layout wasn't found, make a custom one from bits.
+            if (audio_channel_mask_t bitMask =
+                    aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+                            aidl.get<Tag::layoutMask>(), isInput);
+                    bitMask != AUDIO_CHANNEL_NONE) {
+                return bitMask;
+            }
+            return unexpected(BAD_VALUE);
+        case Tag::voiceMask:
+            return convert(aidl, mVoice, __func__, "voice");
+    }
+    ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
+    return unexpected(BAD_VALUE);
+}
+
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+        audio_channel_mask_t legacy, bool isInput) {
+    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
+    const int legacyInitial = legacy; // for error message
+    int aidlLayout = 0;
+    for (const auto& bitPair : bitMapping) {
+        if ((legacy & bitPair.first) == bitPair.first) {
+            aidlLayout |= bitPair.second;
+            legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
+            if (legacy == 0) {
+                return aidlLayout;
+            }
+        }
+    }
+    ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
+            __func__, isInput ? "input" : "output", legacyInitial, legacy);
+    return 0;
+}
+
+ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+        audio_channel_mask_t legacy, bool isInput) {
+    using DirectMap = std::map<audio_channel_mask_t, AudioChannelLayout>;
+    using Tag = AudioChannelLayout::Tag;
+    static const DirectMap mInAndVoice = make_DirectMap(
+            getInAudioChannelPairs(), getVoiceAudioChannelPairs());
+    static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
+
+    auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
+            const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
+        if (auto it = m.find(legacy); it != m.end()) {
+            return it->second;
+        } else {
+            ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
+                    func, type, legacy);
+            return unexpected(BAD_VALUE);
+        }
+    };
+
+    if (legacy == AUDIO_CHANNEL_NONE) {
+        return AudioChannelLayout{};
+    } else if (legacy == AUDIO_CHANNEL_INVALID) {
+        return AudioChannelLayout::make<Tag::invalid>(0);
+    }
+
+    const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
+    if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+        if (audio_channel_mask_is_valid(legacy)) {
+            const int indexMask = VALUE_OR_RETURN(
+                    convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
+            return AudioChannelLayout::make<Tag::indexMask>(indexMask);
+        } else {
+            ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
+            return unexpected(BAD_VALUE);
+        }
+    } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
+        // The fast path is to find a direct match for some known layout mask.
+        if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
+                isInput ? "input / voice" : "output");
+                layoutMatch.ok()) {
+            return layoutMatch;
+        }
+        // If a match for a predefined layout wasn't found, make a custom one from bits,
+        // rejecting those with voice channel bits.
+        if (!isInput ||
+                (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
+            if (int bitMaskLayout =
+                    legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+                            legacy, isInput);
+                    bitMaskLayout != 0) {
+                return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
+            }
+        } else {
+            ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
+                    __func__, legacy);
+        }
+        return unexpected(BAD_VALUE);
+    }
+
+    ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
+            __func__, repr, legacy);
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+        const AudioDeviceDescription& aidl) {
+    static const std::map<AudioDeviceDescription, audio_devices_t> m =
+            make_ReverseMap(getAudioDevicePairs());
+    if (auto it = m.find(aidl); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
+        audio_devices_t legacy) {
+    static const std::map<audio_devices_t, AudioDeviceDescription> m =
+            make_DirectMap(getAudioDevicePairs());
+    if (auto it = m.find(legacy); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
+                __func__, legacy);
+        return unexpected(BAD_VALUE);
+    }
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const AudioDevice& aidl,
+        audio_devices_t* legacyType, char* legacyAddress) {
+    *legacyType = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+    return aidl2legacy_string(
+                    aidl.address.get<AudioDeviceAddress::id>(),
+                    legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const AudioDevice& aidl,
+        audio_devices_t* legacyType, String8* legacyAddress) {
+    *legacyType = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+    *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
+                    aidl.address.get<AudioDeviceAddress::id>()));
+    return OK;
+}
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const AudioDevice& aidl,
+        audio_devices_t* legacyType, std::string* legacyAddress) {
+    *legacyType = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
+    *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
+    return OK;
+}
+
+ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const char* legacyAddress) {
+    AudioDevice aidl;
+    aidl.type = VALUE_OR_RETURN(
+            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+    const std::string aidl_id = VALUE_OR_RETURN(
+            legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
+    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+    return aidl;
+}
+
+ConversionResult<AudioDevice>
+legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const String8& legacyAddress) {
+    AudioDevice aidl;
+    aidl.type = VALUE_OR_RETURN(
+            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
+    const std::string aidl_id = VALUE_OR_RETURN(
+            legacy2aidl_String8_string(legacyAddress));
+    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
+    return aidl;
+}
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+        const AudioFormatDescription& aidl) {
+    static const std::map<AudioFormatDescription, audio_format_t> m =
+            make_ReverseMap(getAudioFormatPairs());
+    if (auto it = m.find(aidl); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
+        audio_format_t legacy) {
+    static const std::map<audio_format_t, AudioFormatDescription> m =
+            make_DirectMap(getAudioFormatPairs());
+    if (auto it = m.find(legacy); it != m.end()) {
+        return it->second;
+    } else {
+        ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
+                __func__, legacy);
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
+        AudioGainMode aidl) {
+    switch (aidl) {
+        case AudioGainMode::JOINT:
+            return AUDIO_GAIN_MODE_JOINT;
+        case AudioGainMode::CHANNELS:
+            return AUDIO_GAIN_MODE_CHANNELS;
+        case AudioGainMode::RAMP:
+            return AUDIO_GAIN_MODE_RAMP;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
+        audio_gain_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_GAIN_MODE_JOINT:
+            return AudioGainMode::JOINT;
+        case AUDIO_GAIN_MODE_CHANNELS:
+            return AudioGainMode::CHANNELS;
+        case AUDIO_GAIN_MODE_RAMP:
+            return AudioGainMode::RAMP;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
+    return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
+            aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
+            // AudioGainMode is index-based.
+            indexToEnum_index<AudioGainMode>,
+            // AUDIO_GAIN_MODE_* constants are mask-based.
+            enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
+    return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
+            legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
+            // AUDIO_GAIN_MODE_* constants are mask-based.
+            indexToEnum_bitmask<audio_gain_mode_t>,
+            // AudioGainMode is index-based.
+            enumToMask_index<int32_t, AudioGainMode>);
+}
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+        const AudioGainConfig& aidl, bool isInput) {
+    audio_gain_config legacy;
+    legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
+    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+    legacy.channel_mask = VALUE_OR_RETURN(
+            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+    const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
+    size_t numValues = isJoint ? 1
+                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
+    if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
+        return unexpected(BAD_VALUE);
+    }
+    for (size_t i = 0; i < numValues; ++i) {
+        legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
+    }
+    legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<int>(aidl.rampDurationMs));
+    return legacy;
+}
+
+ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
+        const audio_gain_config& legacy, bool isInput) {
+    AudioGainConfig aidl;
+    aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
+    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
+    size_t numValues = isJoint ? 1
+                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
+                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
+    aidl.values.resize(numValues);
+    for (size_t i = 0; i < numValues; ++i) {
+        aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
+    }
+    aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
+    return aidl;
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
+        AudioInputFlags aidl) {
+    switch (aidl) {
+        case AudioInputFlags::FAST:
+            return AUDIO_INPUT_FLAG_FAST;
+        case AudioInputFlags::HW_HOTWORD:
+            return AUDIO_INPUT_FLAG_HW_HOTWORD;
+        case AudioInputFlags::RAW:
+            return AUDIO_INPUT_FLAG_RAW;
+        case AudioInputFlags::SYNC:
+            return AUDIO_INPUT_FLAG_SYNC;
+        case AudioInputFlags::MMAP_NOIRQ:
+            return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
+        case AudioInputFlags::VOIP_TX:
+            return AUDIO_INPUT_FLAG_VOIP_TX;
+        case AudioInputFlags::HW_AV_SYNC:
+            return AUDIO_INPUT_FLAG_HW_AV_SYNC;
+        case AudioInputFlags::DIRECT:
+            return AUDIO_INPUT_FLAG_DIRECT;
+        case AudioInputFlags::ULTRASOUND:
+            return AUDIO_INPUT_FLAG_ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
+        audio_input_flags_t legacy) {
+    switch (legacy) {
+        case AUDIO_INPUT_FLAG_NONE:
+            break; // shouldn't get here. must be listed  -Werror,-Wswitch
+        case AUDIO_INPUT_FLAG_FAST:
+            return AudioInputFlags::FAST;
+        case AUDIO_INPUT_FLAG_HW_HOTWORD:
+            return AudioInputFlags::HW_HOTWORD;
+        case AUDIO_INPUT_FLAG_RAW:
+            return AudioInputFlags::RAW;
+        case AUDIO_INPUT_FLAG_SYNC:
+            return AudioInputFlags::SYNC;
+        case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
+            return AudioInputFlags::MMAP_NOIRQ;
+        case AUDIO_INPUT_FLAG_VOIP_TX:
+            return AudioInputFlags::VOIP_TX;
+        case AUDIO_INPUT_FLAG_HW_AV_SYNC:
+            return AudioInputFlags::HW_AV_SYNC;
+        case AUDIO_INPUT_FLAG_DIRECT:
+            return AudioInputFlags::DIRECT;
+        case AUDIO_INPUT_FLAG_ULTRASOUND:
+            return AudioInputFlags::ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
+        AudioOutputFlags aidl) {
+    switch (aidl) {
+        case AudioOutputFlags::DIRECT:
+            return AUDIO_OUTPUT_FLAG_DIRECT;
+        case AudioOutputFlags::PRIMARY:
+            return AUDIO_OUTPUT_FLAG_PRIMARY;
+        case AudioOutputFlags::FAST:
+            return AUDIO_OUTPUT_FLAG_FAST;
+        case AudioOutputFlags::DEEP_BUFFER:
+            return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+        case AudioOutputFlags::COMPRESS_OFFLOAD:
+            return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
+        case AudioOutputFlags::NON_BLOCKING:
+            return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
+        case AudioOutputFlags::HW_AV_SYNC:
+            return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
+        case AudioOutputFlags::TTS:
+            return AUDIO_OUTPUT_FLAG_TTS;
+        case AudioOutputFlags::RAW:
+            return AUDIO_OUTPUT_FLAG_RAW;
+        case AudioOutputFlags::SYNC:
+            return AUDIO_OUTPUT_FLAG_SYNC;
+        case AudioOutputFlags::IEC958_NONAUDIO:
+            return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
+        case AudioOutputFlags::DIRECT_PCM:
+            return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
+        case AudioOutputFlags::MMAP_NOIRQ:
+            return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+        case AudioOutputFlags::VOIP_RX:
+            return AUDIO_OUTPUT_FLAG_VOIP_RX;
+        case AudioOutputFlags::INCALL_MUSIC:
+            return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
+        case AudioOutputFlags::GAPLESS_OFFLOAD:
+            return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
+        case AudioOutputFlags::ULTRASOUND:
+            return AUDIO_OUTPUT_FLAG_ULTRASOUND;
+        case AudioOutputFlags::SPATIALIZER:
+            return AUDIO_OUTPUT_FLAG_SPATIALIZER;
+        case AudioOutputFlags::BIT_PERFECT:
+            return AUDIO_OUTPUT_FLAG_BIT_PERFECT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
+        audio_output_flags_t legacy) {
+    switch (legacy) {
+        case AUDIO_OUTPUT_FLAG_NONE:
+            break; // shouldn't get here. must be listed  -Werror,-Wswitch
+        case AUDIO_OUTPUT_FLAG_DIRECT:
+            return AudioOutputFlags::DIRECT;
+        case AUDIO_OUTPUT_FLAG_PRIMARY:
+            return AudioOutputFlags::PRIMARY;
+        case AUDIO_OUTPUT_FLAG_FAST:
+            return AudioOutputFlags::FAST;
+        case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
+            return AudioOutputFlags::DEEP_BUFFER;
+        case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
+            return AudioOutputFlags::COMPRESS_OFFLOAD;
+        case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
+            return AudioOutputFlags::NON_BLOCKING;
+        case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
+            return AudioOutputFlags::HW_AV_SYNC;
+        case AUDIO_OUTPUT_FLAG_TTS:
+            return AudioOutputFlags::TTS;
+        case AUDIO_OUTPUT_FLAG_RAW:
+            return AudioOutputFlags::RAW;
+        case AUDIO_OUTPUT_FLAG_SYNC:
+            return AudioOutputFlags::SYNC;
+        case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
+            return AudioOutputFlags::IEC958_NONAUDIO;
+        case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
+            return AudioOutputFlags::DIRECT_PCM;
+        case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
+            return AudioOutputFlags::MMAP_NOIRQ;
+        case AUDIO_OUTPUT_FLAG_VOIP_RX:
+            return AudioOutputFlags::VOIP_RX;
+        case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
+            return AudioOutputFlags::INCALL_MUSIC;
+        case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
+            return AudioOutputFlags::GAPLESS_OFFLOAD;
+        case AUDIO_OUTPUT_FLAG_ULTRASOUND:
+            return AudioOutputFlags::ULTRASOUND;
+        case AUDIO_OUTPUT_FLAG_SPATIALIZER:
+            return AudioOutputFlags::SPATIALIZER;
+        case AUDIO_OUTPUT_FLAG_BIT_PERFECT:
+            return AudioOutputFlags::BIT_PERFECT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+        int32_t aidl) {
+    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+    LegacyMask converted = VALUE_OR_RETURN(
+            (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
+                    aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
+                    indexToEnum_index<AudioInputFlags>,
+                    enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
+    return static_cast<audio_input_flags_t>(converted);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+        audio_input_flags_t legacy) {
+    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
+
+    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+    return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
+            legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
+            indexToEnum_bitmask<audio_input_flags_t>,
+            enumToMask_index<int32_t, AudioInputFlags>);
+}
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+        int32_t aidl) {
+    return convertBitmask<audio_output_flags_t,
+            int32_t,
+            audio_output_flags_t,
+            AudioOutputFlags>(
+            aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
+            indexToEnum_index<AudioOutputFlags>,
+            enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+        audio_output_flags_t legacy) {
+    using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
+
+    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
+    return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
+            legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
+            indexToEnum_bitmask<audio_output_flags_t>,
+            enumToMask_index<int32_t, AudioOutputFlags>);
+}
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+        const AudioIoFlags& aidl, bool isInput) {
+    audio_io_flags legacy;
+    if (isInput) {
+        legacy.input = VALUE_OR_RETURN(
+                aidl2legacy_int32_t_audio_input_flags_t_mask(
+                        VALUE_OR_RETURN(UNION_GET(aidl, input))));
+    } else {
+        legacy.output = VALUE_OR_RETURN(
+                aidl2legacy_int32_t_audio_output_flags_t_mask(
+                        VALUE_OR_RETURN(UNION_GET(aidl, output))));
+    }
+    return legacy;
+}
+
+ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+        const audio_io_flags& legacy, bool isInput) {
+    AudioIoFlags aidl;
+    if (isInput) {
+        UNION_SET(aidl, input,
+                VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
+    } else {
+        UNION_SET(aidl, output,
+                VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
+    }
+    return aidl;
+}
+
+ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
+        AudioStreamType aidl) {
+    switch (aidl) {
+        case AudioStreamType::INVALID:
+            break;  // return error
+        case AudioStreamType::SYS_RESERVED_DEFAULT:
+            return AUDIO_STREAM_DEFAULT;
+        case AudioStreamType::VOICE_CALL:
+            return AUDIO_STREAM_VOICE_CALL;
+        case AudioStreamType::SYSTEM:
+            return AUDIO_STREAM_SYSTEM;
+        case AudioStreamType::RING:
+            return AUDIO_STREAM_RING;
+        case AudioStreamType::MUSIC:
+            return AUDIO_STREAM_MUSIC;
+        case AudioStreamType::ALARM:
+            return AUDIO_STREAM_ALARM;
+        case AudioStreamType::NOTIFICATION:
+            return AUDIO_STREAM_NOTIFICATION;
+        case AudioStreamType::BLUETOOTH_SCO:
+            return AUDIO_STREAM_BLUETOOTH_SCO;
+        case AudioStreamType::ENFORCED_AUDIBLE:
+            return AUDIO_STREAM_ENFORCED_AUDIBLE;
+        case AudioStreamType::DTMF:
+            return AUDIO_STREAM_DTMF;
+        case AudioStreamType::TTS:
+            return AUDIO_STREAM_TTS;
+        case AudioStreamType::ACCESSIBILITY:
+            return AUDIO_STREAM_ACCESSIBILITY;
+        case AudioStreamType::ASSISTANT:
+            return AUDIO_STREAM_ASSISTANT;
+        case AudioStreamType::SYS_RESERVED_REROUTING:
+            return AUDIO_STREAM_REROUTING;
+        case AudioStreamType::SYS_RESERVED_PATCH:
+            return AUDIO_STREAM_PATCH;
+        case AudioStreamType::CALL_ASSISTANT:
+            return AUDIO_STREAM_CALL_ASSISTANT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
+        audio_stream_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_STREAM_DEFAULT:
+            return AudioStreamType::SYS_RESERVED_DEFAULT;
+        case AUDIO_STREAM_VOICE_CALL:
+            return AudioStreamType::VOICE_CALL;
+        case AUDIO_STREAM_SYSTEM:
+            return AudioStreamType::SYSTEM;
+        case AUDIO_STREAM_RING:
+            return AudioStreamType::RING;
+        case AUDIO_STREAM_MUSIC:
+            return AudioStreamType::MUSIC;
+        case AUDIO_STREAM_ALARM:
+            return AudioStreamType::ALARM;
+        case AUDIO_STREAM_NOTIFICATION:
+            return AudioStreamType::NOTIFICATION;
+        case AUDIO_STREAM_BLUETOOTH_SCO:
+            return AudioStreamType::BLUETOOTH_SCO;
+        case AUDIO_STREAM_ENFORCED_AUDIBLE:
+            return AudioStreamType::ENFORCED_AUDIBLE;
+        case AUDIO_STREAM_DTMF:
+            return AudioStreamType::DTMF;
+        case AUDIO_STREAM_TTS:
+            return AudioStreamType::TTS;
+        case AUDIO_STREAM_ACCESSIBILITY:
+            return AudioStreamType::ACCESSIBILITY;
+        case AUDIO_STREAM_ASSISTANT:
+            return AudioStreamType::ASSISTANT;
+        case AUDIO_STREAM_REROUTING:
+            return AudioStreamType::SYS_RESERVED_REROUTING;
+        case AUDIO_STREAM_PATCH:
+            return AudioStreamType::SYS_RESERVED_PATCH;
+        case AUDIO_STREAM_CALL_ASSISTANT:
+            return AudioStreamType::CALL_ASSISTANT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+        AudioSource aidl) {
+    switch (aidl) {
+        case AudioSource::SYS_RESERVED_INVALID:
+            return AUDIO_SOURCE_INVALID;
+        case AudioSource::DEFAULT:
+            return AUDIO_SOURCE_DEFAULT;
+        case AudioSource::MIC:
+            return AUDIO_SOURCE_MIC;
+        case AudioSource::VOICE_UPLINK:
+            return AUDIO_SOURCE_VOICE_UPLINK;
+        case AudioSource::VOICE_DOWNLINK:
+            return AUDIO_SOURCE_VOICE_DOWNLINK;
+        case AudioSource::VOICE_CALL:
+            return AUDIO_SOURCE_VOICE_CALL;
+        case AudioSource::CAMCORDER:
+            return AUDIO_SOURCE_CAMCORDER;
+        case AudioSource::VOICE_RECOGNITION:
+            return AUDIO_SOURCE_VOICE_RECOGNITION;
+        case AudioSource::VOICE_COMMUNICATION:
+            return AUDIO_SOURCE_VOICE_COMMUNICATION;
+        case AudioSource::REMOTE_SUBMIX:
+            return AUDIO_SOURCE_REMOTE_SUBMIX;
+        case AudioSource::UNPROCESSED:
+            return AUDIO_SOURCE_UNPROCESSED;
+        case AudioSource::VOICE_PERFORMANCE:
+            return AUDIO_SOURCE_VOICE_PERFORMANCE;
+        case AudioSource::ULTRASOUND:
+            return AUDIO_SOURCE_ULTRASOUND;
+        case AudioSource::ECHO_REFERENCE:
+            return AUDIO_SOURCE_ECHO_REFERENCE;
+        case AudioSource::FM_TUNER:
+            return AUDIO_SOURCE_FM_TUNER;
+        case AudioSource::HOTWORD:
+            return AUDIO_SOURCE_HOTWORD;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
+        audio_source_t legacy) {
+    switch (legacy) {
+        case AUDIO_SOURCE_INVALID:
+            return AudioSource::SYS_RESERVED_INVALID;
+        case AUDIO_SOURCE_DEFAULT:
+            return AudioSource::DEFAULT;
+        case AUDIO_SOURCE_MIC:
+            return AudioSource::MIC;
+        case AUDIO_SOURCE_VOICE_UPLINK:
+            return AudioSource::VOICE_UPLINK;
+        case AUDIO_SOURCE_VOICE_DOWNLINK:
+            return AudioSource::VOICE_DOWNLINK;
+        case AUDIO_SOURCE_VOICE_CALL:
+            return AudioSource::VOICE_CALL;
+        case AUDIO_SOURCE_CAMCORDER:
+            return AudioSource::CAMCORDER;
+        case AUDIO_SOURCE_VOICE_RECOGNITION:
+            return AudioSource::VOICE_RECOGNITION;
+        case AUDIO_SOURCE_VOICE_COMMUNICATION:
+            return AudioSource::VOICE_COMMUNICATION;
+        case AUDIO_SOURCE_REMOTE_SUBMIX:
+            return AudioSource::REMOTE_SUBMIX;
+        case AUDIO_SOURCE_UNPROCESSED:
+            return AudioSource::UNPROCESSED;
+        case AUDIO_SOURCE_VOICE_PERFORMANCE:
+            return AudioSource::VOICE_PERFORMANCE;
+        case AUDIO_SOURCE_ULTRASOUND:
+            return AudioSource::ULTRASOUND;
+        case AUDIO_SOURCE_ECHO_REFERENCE:
+            return AudioSource::ECHO_REFERENCE;
+        case AUDIO_SOURCE_FM_TUNER:
+            return AudioSource::FM_TUNER;
+        case AUDIO_SOURCE_HOTWORD:
+            return AudioSource::HOTWORD;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
+    return convertReinterpret<audio_session_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
+    switch (aidl) {
+        case AudioContentType::UNKNOWN:
+            return AUDIO_CONTENT_TYPE_UNKNOWN;
+        case AudioContentType::SPEECH:
+            return AUDIO_CONTENT_TYPE_SPEECH;
+        case AudioContentType::MUSIC:
+            return AUDIO_CONTENT_TYPE_MUSIC;
+        case AudioContentType::MOVIE:
+            return AUDIO_CONTENT_TYPE_MOVIE;
+        case AudioContentType::SONIFICATION:
+            return AUDIO_CONTENT_TYPE_SONIFICATION;
+        case AudioContentType::ULTRASOUND:
+            return AUDIO_CONTENT_TYPE_ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_CONTENT_TYPE_UNKNOWN:
+            return AudioContentType::UNKNOWN;
+        case AUDIO_CONTENT_TYPE_SPEECH:
+            return AudioContentType::SPEECH;
+        case AUDIO_CONTENT_TYPE_MUSIC:
+            return AudioContentType::MUSIC;
+        case AUDIO_CONTENT_TYPE_MOVIE:
+            return AudioContentType::MOVIE;
+        case AUDIO_CONTENT_TYPE_SONIFICATION:
+            return AudioContentType::SONIFICATION;
+        case AUDIO_CONTENT_TYPE_ULTRASOUND:
+            return AudioContentType::ULTRASOUND;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_usage_t>
+aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
+    switch (aidl) {
+        case AudioUsage::INVALID:
+            break;  // return error
+        case AudioUsage::UNKNOWN:
+            return AUDIO_USAGE_UNKNOWN;
+        case AudioUsage::MEDIA:
+            return AUDIO_USAGE_MEDIA;
+        case AudioUsage::VOICE_COMMUNICATION:
+            return AUDIO_USAGE_VOICE_COMMUNICATION;
+        case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
+            return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
+        case AudioUsage::ALARM:
+            return AUDIO_USAGE_ALARM;
+        case AudioUsage::NOTIFICATION:
+            return AUDIO_USAGE_NOTIFICATION;
+        case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
+            return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
+        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
+        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
+            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
+        case AudioUsage::NOTIFICATION_EVENT:
+            return AUDIO_USAGE_NOTIFICATION_EVENT;
+        case AudioUsage::ASSISTANCE_ACCESSIBILITY:
+            return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
+        case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
+            return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
+        case AudioUsage::ASSISTANCE_SONIFICATION:
+            return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
+        case AudioUsage::GAME:
+            return AUDIO_USAGE_GAME;
+        case AudioUsage::VIRTUAL_SOURCE:
+            return AUDIO_USAGE_VIRTUAL_SOURCE;
+        case AudioUsage::ASSISTANT:
+            return AUDIO_USAGE_ASSISTANT;
+        case AudioUsage::CALL_ASSISTANT:
+            return AUDIO_USAGE_CALL_ASSISTANT;
+        case AudioUsage::EMERGENCY:
+            return AUDIO_USAGE_EMERGENCY;
+        case AudioUsage::SAFETY:
+            return AUDIO_USAGE_SAFETY;
+        case AudioUsage::VEHICLE_STATUS:
+            return AUDIO_USAGE_VEHICLE_STATUS;
+        case AudioUsage::ANNOUNCEMENT:
+            return AUDIO_USAGE_ANNOUNCEMENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioUsage>
+legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
+    switch (legacy) {
+        case AUDIO_USAGE_UNKNOWN:
+            return AudioUsage::UNKNOWN;
+        case AUDIO_USAGE_MEDIA:
+            return AudioUsage::MEDIA;
+        case AUDIO_USAGE_VOICE_COMMUNICATION:
+            return AudioUsage::VOICE_COMMUNICATION;
+        case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
+            return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
+        case AUDIO_USAGE_ALARM:
+            return AudioUsage::ALARM;
+        case AUDIO_USAGE_NOTIFICATION:
+            return AudioUsage::NOTIFICATION;
+        case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
+            return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
+            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
+        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
+            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
+        case AUDIO_USAGE_NOTIFICATION_EVENT:
+            return AudioUsage::NOTIFICATION_EVENT;
+        case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
+            return AudioUsage::ASSISTANCE_ACCESSIBILITY;
+        case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+            return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
+        case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
+            return AudioUsage::ASSISTANCE_SONIFICATION;
+        case AUDIO_USAGE_GAME:
+            return AudioUsage::GAME;
+        case AUDIO_USAGE_VIRTUAL_SOURCE:
+            return AudioUsage::VIRTUAL_SOURCE;
+        case AUDIO_USAGE_ASSISTANT:
+            return AudioUsage::ASSISTANT;
+        case AUDIO_USAGE_CALL_ASSISTANT:
+            return AudioUsage::CALL_ASSISTANT;
+        case AUDIO_USAGE_EMERGENCY:
+            return AudioUsage::EMERGENCY;
+        case AUDIO_USAGE_SAFETY:
+            return AudioUsage::SAFETY;
+        case AUDIO_USAGE_VEHICLE_STATUS:
+            return AudioUsage::VEHICLE_STATUS;
+        case AUDIO_USAGE_ANNOUNCEMENT:
+            return AudioUsage::ANNOUNCEMENT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
+    switch (aidl) {
+        case AudioEncapsulationMode::INVALID:
+            break;  // return error
+        case AudioEncapsulationMode::NONE:
+            return AUDIO_ENCAPSULATION_MODE_NONE;
+        case AudioEncapsulationMode::ELEMENTARY_STREAM:
+            return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
+        case AudioEncapsulationMode::HANDLE:
+            return AUDIO_ENCAPSULATION_MODE_HANDLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_MODE_NONE:
+            return AudioEncapsulationMode::NONE;
+        case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
+            return AudioEncapsulationMode::ELEMENTARY_STREAM;
+        case AUDIO_ENCAPSULATION_MODE_HANDLE:
+            return AudioEncapsulationMode::HANDLE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
+    audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
+    audio_config_base_t base = VALUE_OR_RETURN(
+            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
+    legacy.sample_rate = base.sample_rate;
+    legacy.channel_mask = base.channel_mask;
+    legacy.format = base.format;
+    legacy.stream_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
+    legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<int32_t>(aidl.bitRatePerSecond));
+    legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
+    legacy.has_video = aidl.hasVideo;
+    legacy.is_streaming = aidl.isStreaming;
+    legacy.bit_width = VALUE_OR_RETURN(convertIntegral<int32_t>(aidl.bitWidth));
+    legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<int32_t>(aidl.offloadBufferSize));
+    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+    legacy.encapsulation_mode = VALUE_OR_RETURN(
+            aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
+    legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
+    legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
+    return legacy;
+}
+
+ConversionResult<AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
+    AudioOffloadInfo aidl;
+    // Version 0.1 fields.
+    if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
+        return unexpected(BAD_VALUE);
+    }
+    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+        .channel_mask = legacy.channel_mask, .format = legacy.format };
+    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
+                    base, false /*isInput*/));
+    aidl.streamType = VALUE_OR_RETURN(
+            legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
+    aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
+    aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
+    aidl.hasVideo = legacy.has_video;
+    aidl.isStreaming = legacy.is_streaming;
+    aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
+    aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
+    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
+
+    // Version 0.2 fields.
+    if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
+        if (legacy.size <
+            offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
+            return unexpected(BAD_VALUE);
+        }
+        aidl.encapsulationMode = VALUE_OR_RETURN(
+                legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
+                        legacy.encapsulation_mode));
+        aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
+        aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
+    }
+    return aidl;
+}
+
+ConversionResult<AudioPortDirection> portDirection(audio_port_role_t role, audio_port_type_t type) {
+    switch (type) {
+        case AUDIO_PORT_TYPE_NONE:
+        case AUDIO_PORT_TYPE_SESSION:
+            break;  // must be listed  -Werror,-Wswitch
+        case AUDIO_PORT_TYPE_DEVICE:
+            switch (role) {
+                case AUDIO_PORT_ROLE_NONE:
+                     break;  // must be listed  -Werror,-Wswitch
+                case AUDIO_PORT_ROLE_SOURCE:
+                    return AudioPortDirection::INPUT;
+                case AUDIO_PORT_ROLE_SINK:
+                    return AudioPortDirection::OUTPUT;
+            }
+            break;
+        case AUDIO_PORT_TYPE_MIX:
+            switch (role) {
+                case AUDIO_PORT_ROLE_NONE:
+                     break;  // must be listed  -Werror,-Wswitch
+                case AUDIO_PORT_ROLE_SOURCE:
+                    return AudioPortDirection::OUTPUT;
+                case AUDIO_PORT_ROLE_SINK:
+                    return AudioPortDirection::INPUT;
+            }
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_port_role_t> portRole(AudioPortDirection direction, audio_port_type_t type) {
+    switch (type) {
+        case AUDIO_PORT_TYPE_NONE:
+        case AUDIO_PORT_TYPE_SESSION:
+            break;  // must be listed  -Werror,-Wswitch
+        case AUDIO_PORT_TYPE_DEVICE:
+            switch (direction) {
+                case AudioPortDirection::INPUT:
+                    return AUDIO_PORT_ROLE_SOURCE;
+                case AudioPortDirection::OUTPUT:
+                    return AUDIO_PORT_ROLE_SINK;
+            }
+            break;
+        case AUDIO_PORT_TYPE_MIX:
+            switch (direction) {
+                case AudioPortDirection::OUTPUT:
+                    return AUDIO_PORT_ROLE_SOURCE;
+                case AudioPortDirection::INPUT:
+                    return AUDIO_PORT_ROLE_SINK;
+            }
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
+    const audio_config_base_t legacyBase = VALUE_OR_RETURN(
+            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
+    audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
+    legacy.sample_rate = legacyBase.sample_rate;
+    legacy.channel_mask = legacyBase.channel_mask;
+    legacy.format = legacyBase.format;
+    legacy.offload_info = VALUE_OR_RETURN(
+            aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
+    legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
+    return legacy;
+}
+
+ConversionResult<AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
+    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
+        .channel_mask = legacy.channel_mask, .format = legacy.format };
+    AudioConfig aidl;
+    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
+    aidl.offloadInfo = VALUE_OR_RETURN(
+            legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
+    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
+    return aidl;
+}
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
+    audio_config_base_t legacy;
+    legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<int>(aidl.sampleRate));
+    legacy.channel_mask = VALUE_OR_RETURN(
+            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+    return legacy;
+}
+
+ConversionResult<AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
+    AudioConfigBase aidl;
+    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+    return aidl;
+}
+
+ConversionResult<audio_uuid_t>
+aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
+    audio_uuid_t legacy;
+    legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
+    legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
+    legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
+    legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
+    if (aidl.node.size() != std::size(legacy.node)) {
+        return unexpected(BAD_VALUE);
+    }
+    std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
+    return legacy;
+}
+
+ConversionResult<AudioUuid>
+legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
+    AudioUuid aidl;
+    aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
+    aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
+    aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
+    aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
+    std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
+    return aidl;
+}
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+        AudioEncapsulationMetadataType aidl) {
+    switch (aidl) {
+        case AudioEncapsulationMetadataType::NONE:
+            return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
+        case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
+            return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
+        case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
+            return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+        audio_encapsulation_metadata_type_t legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
+            return AudioEncapsulationMetadataType::NONE;
+        case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
+            return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
+        case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
+            return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
+    return convertBitmask<uint32_t,
+            int32_t,
+            audio_encapsulation_mode_t,
+            AudioEncapsulationMode>(
+            aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
+            indexToEnum_index<AudioEncapsulationMode>,
+            enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
+    return convertBitmask<int32_t,
+            uint32_t,
+            AudioEncapsulationMode,
+            audio_encapsulation_mode_t>(
+            legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
+            indexToEnum_index<audio_encapsulation_mode_t>,
+            enumToMask_index<int32_t, AudioEncapsulationMode>);
+}
+
+ConversionResult<uint32_t>
+aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
+    return convertBitmask<uint32_t,
+            int32_t,
+            audio_encapsulation_metadata_type_t,
+            AudioEncapsulationMetadataType>(
+            aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
+            indexToEnum_index<AudioEncapsulationMetadataType>,
+            enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
+}
+
+ConversionResult<int32_t>
+legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
+    return convertBitmask<int32_t,
+            uint32_t,
+            AudioEncapsulationMetadataType,
+            audio_encapsulation_metadata_type_t>(
+            legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
+            indexToEnum_index<audio_encapsulation_metadata_type_t>,
+            enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
+}
+
+ConversionResult<audio_port_config_mix_ext_usecase>
+aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+        const AudioPortMixExtUseCase& aidl, bool isInput) {
+    audio_port_config_mix_ext_usecase legacy{};
+    if (aidl.getTag() != AudioPortMixExtUseCase::Tag::unspecified) {
+        if (!isInput) {
+            legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
+                            VALUE_OR_RETURN(UNION_GET(aidl, stream))));
+        } else {
+            legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
+                            VALUE_OR_RETURN(UNION_GET(aidl, source))));
+        }
+    }
+    return legacy;
+}
+
+ConversionResult<AudioPortMixExtUseCase>
+legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+        const audio_port_config_mix_ext_usecase& legacy, bool isInput) {
+    AudioPortMixExtUseCase aidl;
+    if (!isInput) {
+        UNION_SET(aidl, stream, VALUE_OR_RETURN(
+                        legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
+    } else {
+        UNION_SET(aidl, source, VALUE_OR_RETURN(
+                        legacy2aidl_audio_source_t_AudioSource(legacy.source)));
+    }
+    return aidl;
+}
+
+ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_config_mix_ext(
+        const AudioPortMixExt& aidl, bool isInput) {
+    audio_port_config_mix_ext legacy{};
+    legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+    legacy.usecase = VALUE_OR_RETURN(
+            aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+                    aidl.usecase, isInput));
+    return legacy;
+}
+
+ConversionResult<AudioPortMixExt> legacy2aidl_audio_port_config_mix_ext_AudioPortMixExt(
+        const audio_port_config_mix_ext& legacy, bool isInput) {
+    AudioPortMixExt aidl;
+    aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+    aidl.usecase = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+                    legacy.usecase, isInput));
+    return aidl;
+}
+
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(const AudioPortDeviceExt& aidl) {
+    audio_port_config_device_ext legacy{};
+    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl.device, &legacy.type, legacy.address));
+    return legacy;
+}
+
+ConversionResult<AudioPortDeviceExt> legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+        const audio_port_config_device_ext& legacy) {
+    AudioPortDeviceExt aidl;
+    aidl.device = VALUE_OR_RETURN(
+            legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+    return aidl;
+}
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_config_ext = decltype(audio_port_config::ext);
+
+status_t aidl2legacy_AudioPortExt_audio_port_config_ext(
+        const AudioPortExt& aidl, bool isInput,
+        audio_port_config_ext* legacy, audio_port_type_t* type) {
+    switch (aidl.getTag()) {
+        case AudioPortExt::Tag::unspecified:
+            // Just verify that the union is empty.
+            VALUE_OR_RETURN_STATUS(UNION_GET(aidl, unspecified));
+            *legacy = {};
+            *type = AUDIO_PORT_TYPE_NONE;
+            return OK;
+        case AudioPortExt::Tag::device:
+            legacy->device = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+                            VALUE_OR_RETURN_STATUS(UNION_GET(aidl, device))));
+            *type = AUDIO_PORT_TYPE_DEVICE;
+            return OK;
+        case AudioPortExt::Tag::mix:
+            legacy->mix = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioPortMixExt_audio_port_config_mix_ext(
+                            VALUE_OR_RETURN_STATUS(UNION_GET(aidl, mix)), isInput));
+            *type = AUDIO_PORT_TYPE_MIX;
+            return OK;
+        case AudioPortExt::Tag::session:
+            // This variant is not used in the HAL scenario.
+            legacy->session.session = AUDIO_SESSION_NONE;
+            *type = AUDIO_PORT_TYPE_SESSION;
+            return OK;
+
+    }
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<AudioPortExt> legacy2aidl_audio_port_config_ext_AudioPortExt(
+        const audio_port_config_ext& legacy, audio_port_type_t type, bool isInput) {
+    AudioPortExt aidl;
+    switch (type) {
+        case AUDIO_PORT_TYPE_NONE:
+            UNION_SET(aidl, unspecified, false);
+            return aidl;
+        case AUDIO_PORT_TYPE_DEVICE: {
+            AudioPortDeviceExt device = VALUE_OR_RETURN(
+                    legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(legacy.device));
+            UNION_SET(aidl, device, device);
+            return aidl;
+        }
+        case AUDIO_PORT_TYPE_MIX: {
+            AudioPortMixExt mix = VALUE_OR_RETURN(
+                    legacy2aidl_audio_port_config_mix_ext_AudioPortMixExt(legacy.mix, isInput));
+            UNION_SET(aidl, mix, mix);
+            return aidl;
+        }
+        case AUDIO_PORT_TYPE_SESSION:
+            // This variant is not used in the HAL scenario.
+            UNION_SET(aidl, unspecified, false);
+            return aidl;
+    }
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+status_t aidl2legacy_AudioPortConfig_audio_port_config(
+        const AudioPortConfig& aidl, bool isInput, audio_port_config* legacy, int32_t* portId) {
+    legacy->id = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
+    *portId = aidl.portId;
+    if (aidl.sampleRate.has_value()) {
+        legacy->sample_rate = VALUE_OR_RETURN_STATUS(
+                convertIntegral<unsigned int>(aidl.sampleRate.value().value));
+        legacy->config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
+    }
+    if (aidl.channelMask.has_value()) {
+        legacy->channel_mask =
+                VALUE_OR_RETURN_STATUS(
+                        aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                                aidl.channelMask.value(), isInput));
+        legacy->config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
+    }
+    if (aidl.format.has_value()) {
+        legacy->format = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format.value()));
+        legacy->config_mask |= AUDIO_PORT_CONFIG_FORMAT;
+    }
+    if (aidl.gain.has_value()) {
+        legacy->gain = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioGainConfig_audio_gain_config(
+                        aidl.gain.value(), isInput));
+        legacy->config_mask |= AUDIO_PORT_CONFIG_GAIN;
+    }
+    if (aidl.flags.has_value()) {
+        legacy->flags = VALUE_OR_RETURN_STATUS(
+                aidl2legacy_AudioIoFlags_audio_io_flags(aidl.flags.value(), isInput));
+        legacy->config_mask |= AUDIO_PORT_CONFIG_FLAGS;
+    }
+    RETURN_STATUS_IF_ERROR(aidl2legacy_AudioPortExt_audio_port_config_ext(
+                    aidl.ext, isInput, &legacy->ext, &legacy->type));
+    legacy->role = VALUE_OR_RETURN_STATUS(portRole(isInput ?
+                    AudioPortDirection::INPUT : AudioPortDirection::OUTPUT, legacy->type));
+    return OK;
+}
+
+ConversionResult<AudioPortConfig>
+legacy2aidl_audio_port_config_AudioPortConfig(
+        const audio_port_config& legacy, bool isInput, int32_t portId) {
+    AudioPortConfig aidl;
+    aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+    aidl.portId = portId;
+    if (legacy.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+        Int aidl_sampleRate;
+        aidl_sampleRate.value = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
+        aidl.sampleRate = aidl_sampleRate;
+    }
+    if (legacy.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+        aidl.channelMask = VALUE_OR_RETURN(
+                legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    }
+    if (legacy.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+        aidl.format = VALUE_OR_RETURN(
+                legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+    }
+    if (legacy.config_mask & AUDIO_PORT_CONFIG_GAIN) {
+        aidl.gain = VALUE_OR_RETURN(
+                legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
+    }
+    if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
+        aidl.flags = VALUE_OR_RETURN(
+                legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
+    }
+    aidl.ext = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_config_ext_AudioPortExt(legacy.ext, legacy.type, isInput));
+    return aidl;
+}
+
+ConversionResult<audio_port_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+        const AudioPortMixExt& aidl) {
+    audio_port_mix_ext legacy{};
+    legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
+    return legacy;
+}
+
+ConversionResult<AudioPortMixExt> legacy2aidl_audio_port_mix_ext_AudioPortMixExt(
+        const audio_port_mix_ext& legacy) {
+    AudioPortMixExt aidl;
+    aidl.handle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
+    return aidl;
+}
+
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(const AudioPortDeviceExt& aidl) {
+    audio_port_device_ext legacy{};
+    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidl.device, &legacy.type, legacy.address));
+    legacy.encapsulation_modes = VALUE_OR_RETURN(
+            aidl2legacy_AudioEncapsulationMode_mask(aidl.encapsulationModes));
+    legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
+            aidl2legacy_AudioEncapsulationMetadataType_mask(
+                    aidl.encapsulationMetadataTypes));
+    return legacy;
+}
+
+ConversionResult<AudioPortDeviceExt> legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+        const audio_port_device_ext& legacy) {
+    AudioPortDeviceExt aidl;
+    aidl.device = VALUE_OR_RETURN(
+            legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
+    aidl.encapsulationModes = VALUE_OR_RETURN(
+            legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
+    aidl.encapsulationMetadataTypes = VALUE_OR_RETURN(
+            legacy2aidl_AudioEncapsulationMetadataType_mask(legacy.encapsulation_metadata_types));
+    return aidl;
+}
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_v7_ext = decltype(audio_port_v7::ext);
+
+status_t aidl2legacy_AudioPortExt_audio_port_v7_ext(
+        const AudioPortExt& aidl, audio_port_v7_ext* legacy, audio_port_type_t* type) {
+    switch (aidl.getTag()) {
+        case AudioPortExt::Tag::unspecified:
+            // Just verify that the union is empty.
+            VALUE_OR_RETURN_STATUS(UNION_GET(aidl, unspecified));
+            *legacy = {};
+            *type = AUDIO_PORT_TYPE_NONE;
+            return OK;
+        case AudioPortExt::Tag::device:
+            legacy->device = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+                            VALUE_OR_RETURN_STATUS(UNION_GET(aidl, device))));
+            *type = AUDIO_PORT_TYPE_DEVICE;
+            return OK;
+        case AudioPortExt::Tag::mix:
+            legacy->mix = VALUE_OR_RETURN_STATUS(
+                    aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+                            VALUE_OR_RETURN_STATUS(UNION_GET(aidl, mix))));
+            *type = AUDIO_PORT_TYPE_MIX;
+            return OK;
+        case AudioPortExt::Tag::session:
+            // This variant is not used in the HAL scenario.
+            legacy->session.session = AUDIO_SESSION_NONE;
+            *type = AUDIO_PORT_TYPE_SESSION;
+            return OK;
+
+    }
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<AudioPortExt> legacy2aidl_audio_port_v7_ext_AudioPortExt(
+        const audio_port_v7_ext& legacy, audio_port_type_t type) {
+    AudioPortExt aidl;
+    switch (type) {
+        case AUDIO_PORT_TYPE_NONE:
+            UNION_SET(aidl, unspecified, false);
+            return aidl;
+        case AUDIO_PORT_TYPE_DEVICE: {
+            AudioPortDeviceExt device = VALUE_OR_RETURN(
+                    legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy.device));
+            UNION_SET(aidl, device, device);
+            return aidl;
+        }
+        case AUDIO_PORT_TYPE_MIX: {
+            AudioPortMixExt mix = VALUE_OR_RETURN(
+                    legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy.mix));
+            UNION_SET(aidl, mix, mix);
+            return aidl;
+        }
+        case AUDIO_PORT_TYPE_SESSION:
+            // This variant is not used in the HAL scenario.
+            UNION_SET(aidl, unspecified, false);
+            return aidl;
+    }
+    LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
+}
+
+ConversionResult<audio_port_v7>
+aidl2legacy_AudioPort_audio_port_v7(const AudioPort& aidl, bool isInput) {
+    audio_port_v7 legacy;
+    legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.id));
+    RETURN_IF_ERROR(aidl2legacy_string(aidl.name, legacy.name, sizeof(legacy.name)));
+
+    if (aidl.profiles.size() > std::size(legacy.audio_profiles)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(convertRange(
+                    aidl.profiles.begin(), aidl.profiles.end(), legacy.audio_profiles,
+                    [isInput](const AudioProfile& p) {
+                        return aidl2legacy_AudioProfile_audio_profile(p, isInput);
+                    }));
+    legacy.num_audio_profiles = aidl.profiles.size();
+
+    if (aidl.extraAudioDescriptors.size() > std::size(legacy.extra_audio_descriptors)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(
+                    aidl.extraAudioDescriptors.begin(), aidl.extraAudioDescriptors.end(),
+                    legacy.extra_audio_descriptors,
+                    aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor));
+    legacy.num_extra_audio_descriptors = aidl.extraAudioDescriptors.size();
+
+    if (aidl.gains.size() > std::size(legacy.gains)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(convertRange(aidl.gains.begin(), aidl.gains.end(), legacy.gains,
+                                 [isInput](const AudioGain& g) {
+                                     return aidl2legacy_AudioGain_audio_gain(g, isInput);
+                                 }));
+    legacy.num_gains = aidl.gains.size();
+
+    RETURN_IF_ERROR(aidl2legacy_AudioPortExt_audio_port_v7_ext(
+                    aidl.ext, &legacy.ext, &legacy.type));
+    legacy.role = VALUE_OR_RETURN(portRole(
+                    isInput ? AudioPortDirection::INPUT : AudioPortDirection::OUTPUT, legacy.type));
+
+    AudioPortConfig aidlPortConfig;
+    int32_t portId;
+    aidlPortConfig.flags = aidl.flags;
+    aidlPortConfig.ext = aidl.ext;
+    RETURN_IF_ERROR(aidl2legacy_AudioPortConfig_audio_port_config(
+                    aidlPortConfig, isInput, &legacy.active_config, &portId));
+    return legacy;
+}
+
+ConversionResult<AudioPort>
+legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy, bool isInput) {
+    AudioPort aidl;
+    aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+    aidl.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+
+    if (legacy.num_audio_profiles > std::size(legacy.audio_profiles)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(legacy.audio_profiles, legacy.audio_profiles + legacy.num_audio_profiles,
+                         std::back_inserter(aidl.profiles),
+                         [isInput](const audio_profile& p) {
+                             return legacy2aidl_audio_profile_AudioProfile(p, isInput);
+                         }));
+
+    if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
+        return unexpected(BAD_VALUE);
+    }
+    aidl.profiles.resize(legacy.num_audio_profiles);
+    RETURN_IF_ERROR(
+            convertRange(legacy.extra_audio_descriptors,
+                    legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
+                    std::back_inserter(aidl.extraAudioDescriptors),
+                    legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor));
+
+    if (legacy.num_gains > std::size(legacy.gains)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(legacy.gains, legacy.gains + legacy.num_gains,
+                         std::back_inserter(aidl.gains),
+                         [isInput](const audio_gain& g) {
+                             return legacy2aidl_audio_gain_AudioGain(g, isInput);
+                         }));
+    aidl.gains.resize(legacy.num_gains);
+
+    aidl.ext = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_v7_ext_AudioPortExt(legacy.ext, legacy.type));
+
+    AudioPortConfig aidlPortConfig = VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(
+                    legacy.active_config, isInput, aidl.id));
+    if (aidlPortConfig.flags.has_value()) {
+        aidl.flags = aidlPortConfig.flags.value();
+    } else {
+        aidl.flags = isInput ?
+                AudioIoFlags::make<AudioIoFlags::Tag::input>(0) :
+                AudioIoFlags::make<AudioIoFlags::Tag::output>(0);
+    }
+    return aidl;
+}
+
+ConversionResult<audio_profile>
+aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
+    audio_profile legacy;
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+
+    if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
+                         convertIntegral<int32_t, unsigned int>));
+    legacy.num_sample_rates = aidl.sampleRates.size();
+
+    if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
+                    [isInput](const AudioChannelLayout& l) {
+                        return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
+                    }));
+    legacy.num_channel_masks = aidl.channelMasks.size();
+
+    legacy.encapsulation_type = VALUE_OR_RETURN(
+            aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
+    return legacy;
+}
+
+ConversionResult<AudioProfile>
+legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
+    AudioProfile aidl;
+    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
+
+    if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
+                         std::back_inserter(aidl.sampleRates),
+                         convertIntegral<unsigned int, int32_t>));
+
+    if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
+        return unexpected(BAD_VALUE);
+    }
+    RETURN_IF_ERROR(
+            convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
+                         std::back_inserter(aidl.channelMasks),
+                    [isInput](audio_channel_mask_t m) {
+                        return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
+                    }));
+
+    aidl.encapsulationType = VALUE_OR_RETURN(
+            legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+                    legacy.encapsulation_type));
+    return aidl;
+}
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
+    audio_gain legacy;
+    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
+    legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                    aidl.channelMask, isInput));
+    legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
+    legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
+    legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
+    legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
+    legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
+    legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
+    return legacy;
+}
+
+ConversionResult<AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
+    AudioGain aidl;
+    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
+    aidl.channelMask = VALUE_OR_RETURN(
+            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
+    aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
+    aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
+    aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
+    aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
+    aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
+    aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
+    return aidl;
+}
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
+    switch (aidl) {
+        case AudioMode::SYS_RESERVED_INVALID:
+            return AUDIO_MODE_INVALID;
+        case AudioMode::SYS_RESERVED_CURRENT:
+            return AUDIO_MODE_CURRENT;
+        case AudioMode::NORMAL:
+            return AUDIO_MODE_NORMAL;
+        case AudioMode::RINGTONE:
+            return AUDIO_MODE_RINGTONE;
+        case AudioMode::IN_CALL:
+            return AUDIO_MODE_IN_CALL;
+        case AudioMode::IN_COMMUNICATION:
+            return AUDIO_MODE_IN_COMMUNICATION;
+        case AudioMode::CALL_SCREEN:
+            return AUDIO_MODE_CALL_SCREEN;
+        case AudioMode::SYS_RESERVED_CALL_REDIRECT:
+            return AUDIO_MODE_CALL_REDIRECT;
+        case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
+            return AUDIO_MODE_COMMUNICATION_REDIRECT;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_MODE_INVALID:
+            return AudioMode::SYS_RESERVED_INVALID;
+        case AUDIO_MODE_CURRENT:
+            return AudioMode::SYS_RESERVED_CURRENT;
+        case AUDIO_MODE_NORMAL:
+            return AudioMode::NORMAL;
+        case AUDIO_MODE_RINGTONE:
+            return AudioMode::RINGTONE;
+        case AUDIO_MODE_IN_CALL:
+            return AudioMode::IN_CALL;
+        case AUDIO_MODE_IN_COMMUNICATION:
+            return AudioMode::IN_COMMUNICATION;
+        case AUDIO_MODE_CALL_SCREEN:
+            return AudioMode::CALL_SCREEN;
+        case AUDIO_MODE_CALL_REDIRECT:
+            return AudioMode::SYS_RESERVED_CALL_REDIRECT;
+        case AUDIO_MODE_COMMUNICATION_REDIRECT:
+            return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
+        case AUDIO_MODE_CNT:
+            break;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_standard_t>
+aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
+    switch (aidl) {
+        case AudioStandard::NONE:
+            return AUDIO_STANDARD_NONE;
+        case AudioStandard::EDID:
+            return AUDIO_STANDARD_EDID;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioStandard>
+legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
+    switch (legacy) {
+        case AUDIO_STANDARD_NONE:
+            return AudioStandard::NONE;
+        case AUDIO_STANDARD_EDID:
+            return AudioStandard::EDID;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+        const ExtraAudioDescriptor& aidl) {
+    audio_extra_audio_descriptor legacy;
+    legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
+    if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+        return unexpected(BAD_VALUE);
+    }
+    legacy.descriptor_length = aidl.audioDescriptor.size();
+    std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
+              std::begin(legacy.descriptor));
+    legacy.encapsulation_type =
+            VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+                    aidl.encapsulationType));
+    return legacy;
+}
+
+ConversionResult<ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+        const audio_extra_audio_descriptor& legacy) {
+    ExtraAudioDescriptor aidl;
+    aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
+    if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
+        return unexpected(BAD_VALUE);
+    }
+    aidl.audioDescriptor.resize(legacy.descriptor_length);
+    std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
+              aidl.audioDescriptor.begin());
+    aidl.encapsulationType =
+            VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+                    legacy.encapsulation_type));
+    return aidl;
+}
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+        const AudioEncapsulationType& aidl) {
+    switch (aidl) {
+        case AudioEncapsulationType::NONE:
+            return AUDIO_ENCAPSULATION_TYPE_NONE;
+        case AudioEncapsulationType::IEC61937:
+            return AUDIO_ENCAPSULATION_TYPE_IEC61937;
+        case AudioEncapsulationType::PCM:
+            return AUDIO_ENCAPSULATION_TYPE_PCM;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+        const audio_encapsulation_type_t & legacy) {
+    switch (legacy) {
+        case AUDIO_ENCAPSULATION_TYPE_NONE:
+            return AudioEncapsulationType::NONE;
+        case AUDIO_ENCAPSULATION_TYPE_IEC61937:
+            return AudioEncapsulationType::IEC61937;
+        case AUDIO_ENCAPSULATION_TYPE_PCM:
+            return AudioEncapsulationType::PCM;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(AudioDualMonoMode aidl) {
+    switch (aidl) {
+        case AudioDualMonoMode::OFF:
+            return AUDIO_DUAL_MONO_MODE_OFF;
+        case AudioDualMonoMode::LR:
+            return AUDIO_DUAL_MONO_MODE_LR;
+        case AudioDualMonoMode::LL:
+            return AUDIO_DUAL_MONO_MODE_LL;
+        case AudioDualMonoMode::RR:
+            return AUDIO_DUAL_MONO_MODE_RR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_DUAL_MONO_MODE_OFF:
+            return AudioDualMonoMode::OFF;
+        case AUDIO_DUAL_MONO_MODE_LR:
+            return AudioDualMonoMode::LR;
+        case AUDIO_DUAL_MONO_MODE_LL:
+            return AudioDualMonoMode::LL;
+        case AUDIO_DUAL_MONO_MODE_RR:
+            return AudioDualMonoMode::RR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+        AudioPlaybackRate::TimestretchFallbackMode aidl) {
+    switch (aidl) {
+        case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT:
+            return AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT;
+        case AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT:
+            return AUDIO_TIMESTRETCH_FALLBACK_DEFAULT;
+        case AudioPlaybackRate::TimestretchFallbackMode::MUTE:
+            return AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+        case AudioPlaybackRate::TimestretchFallbackMode::FAIL:
+            return AUDIO_TIMESTRETCH_FALLBACK_FAIL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+        audio_timestretch_fallback_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_TIMESTRETCH_FALLBACK_CUT_REPEAT:
+            return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_CUT_REPEAT;
+        case AUDIO_TIMESTRETCH_FALLBACK_DEFAULT:
+            return AudioPlaybackRate::TimestretchFallbackMode::SYS_RESERVED_DEFAULT;
+        case AUDIO_TIMESTRETCH_FALLBACK_MUTE:
+            return AudioPlaybackRate::TimestretchFallbackMode::MUTE;
+        case AUDIO_TIMESTRETCH_FALLBACK_FAIL:
+            return AudioPlaybackRate::TimestretchFallbackMode::FAIL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+        AudioPlaybackRate::TimestretchMode aidl) {
+    switch (aidl) {
+        case AudioPlaybackRate::TimestretchMode::DEFAULT:
+            return AUDIO_TIMESTRETCH_STRETCH_DEFAULT;
+        case AudioPlaybackRate::TimestretchMode::VOICE:
+            return AUDIO_TIMESTRETCH_STRETCH_VOICE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+        audio_timestretch_stretch_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_TIMESTRETCH_STRETCH_DEFAULT:
+            return AudioPlaybackRate::TimestretchMode::DEFAULT;
+        case AUDIO_TIMESTRETCH_STRETCH_VOICE:
+            return AudioPlaybackRate::TimestretchMode::VOICE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const AudioPlaybackRate& aidl) {
+    audio_playback_rate_t legacy;
+    legacy.mSpeed = aidl.speed;
+    legacy.mPitch = aidl.pitch;
+    legacy.mFallbackMode = VALUE_OR_RETURN(
+            aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+                    aidl.fallbackMode));
+    legacy.mStretchMode = VALUE_OR_RETURN(
+            aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(aidl.timestretchMode));
+    return legacy;
+}
+
+ConversionResult<AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
+    AudioPlaybackRate aidl;
+    aidl.speed = legacy.mSpeed;
+    aidl.pitch = legacy.mPitch;
+    aidl.fallbackMode = VALUE_OR_RETURN(
+            legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+                    legacy.mFallbackMode));
+    aidl.timestretchMode = VALUE_OR_RETURN(
+            legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(legacy.mStretchMode));
+    return aidl;
+}
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(AudioLatencyMode aidl) {
+    switch (aidl) {
+        case AudioLatencyMode::FREE:
+            return AUDIO_LATENCY_MODE_FREE;
+        case AudioLatencyMode::LOW:
+            return AUDIO_LATENCY_MODE_LOW;
+        case AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE:
+            return AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE;
+        case AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE:
+            return AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE;
+    }
+    return unexpected(BAD_VALUE);
+}
+ConversionResult<AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy) {
+    switch (legacy) {
+        case AUDIO_LATENCY_MODE_FREE:
+            return AudioLatencyMode::FREE;
+        case AUDIO_LATENCY_MODE_LOW:
+            return AudioLatencyMode::LOW;
+        case AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_SOFTWARE:
+            return AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_SOFTWARE;
+        case AUDIO_LATENCY_MODE_DYNAMIC_SPATIAL_AUDIO_HARDWARE:
+            return AudioLatencyMode::DYNAMIC_SPATIAL_AUDIO_HARDWARE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_location_t>
+aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(MicrophoneInfo::Location aidl) {
+    switch (aidl) {
+        case MicrophoneInfo::Location::UNKNOWN:
+            return AUDIO_MICROPHONE_LOCATION_UNKNOWN;
+        case MicrophoneInfo::Location::MAINBODY:
+            return AUDIO_MICROPHONE_LOCATION_MAINBODY;
+        case MicrophoneInfo::Location::MAINBODY_MOVABLE:
+            return AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE;
+        case MicrophoneInfo::Location::PERIPHERAL:
+            return AUDIO_MICROPHONE_LOCATION_PERIPHERAL;
+    }
+    return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneInfo::Location>
+legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(audio_microphone_location_t legacy) {
+    switch (legacy) {
+        case AUDIO_MICROPHONE_LOCATION_UNKNOWN:
+            return MicrophoneInfo::Location::UNKNOWN;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY:
+            return MicrophoneInfo::Location::MAINBODY;
+        case AUDIO_MICROPHONE_LOCATION_MAINBODY_MOVABLE:
+            return MicrophoneInfo::Location::MAINBODY_MOVABLE;
+        case AUDIO_MICROPHONE_LOCATION_PERIPHERAL:
+            return MicrophoneInfo::Location::PERIPHERAL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_group_t> aidl2legacy_int32_t_audio_microphone_group_t(
+        int32_t aidl) {
+    return convertReinterpret<audio_microphone_group_t>(aidl);
+}
+
+ConversionResult<int32_t> legacy2aidl_audio_microphone_group_t_int32_t(
+        audio_microphone_group_t legacy) {
+    return convertReinterpret<int32_t>(legacy);
+}
+
+ConversionResult<audio_microphone_directionality_t>
+aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+        MicrophoneInfo::Directionality aidl) {
+    switch (aidl) {
+        case MicrophoneInfo::Directionality::UNKNOWN:
+            return AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN;
+        case MicrophoneInfo::Directionality::OMNI:
+            return AUDIO_MICROPHONE_DIRECTIONALITY_OMNI;
+        case MicrophoneInfo::Directionality::BI_DIRECTIONAL:
+            return AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL;
+        case MicrophoneInfo::Directionality::CARDIOID:
+            return AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID;
+        case MicrophoneInfo::Directionality::HYPER_CARDIOID:
+            return AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID;
+        case MicrophoneInfo::Directionality::SUPER_CARDIOID:
+            return AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID;
+    }
+    return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneInfo::Directionality>
+legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+        audio_microphone_directionality_t legacy) {
+    switch (legacy) {
+        case AUDIO_MICROPHONE_DIRECTIONALITY_UNKNOWN:
+            return MicrophoneInfo::Directionality::UNKNOWN;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_OMNI:
+            return MicrophoneInfo::Directionality::OMNI;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_BI_DIRECTIONAL:
+            return MicrophoneInfo::Directionality::BI_DIRECTIONAL;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_CARDIOID:
+            return MicrophoneInfo::Directionality::CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_HYPER_CARDIOID:
+            return MicrophoneInfo::Directionality::HYPER_CARDIOID;
+        case AUDIO_MICROPHONE_DIRECTIONALITY_SUPER_CARDIOID:
+            return MicrophoneInfo::Directionality::SUPER_CARDIOID;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_coordinate>
+aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+        const MicrophoneInfo::Coordinate& aidl) {
+    audio_microphone_coordinate legacy;
+    legacy.x = aidl.x;
+    legacy.y = aidl.y;
+    legacy.z = aidl.z;
+    return legacy;
+}
+ConversionResult<MicrophoneInfo::Coordinate>
+legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+        const audio_microphone_coordinate& legacy) {
+    MicrophoneInfo::Coordinate aidl;
+    aidl.x = legacy.x;
+    aidl.y = legacy.y;
+    aidl.z = legacy.z;
+    return aidl;
+}
+
+ConversionResult<audio_microphone_channel_mapping_t>
+aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+        MicrophoneDynamicInfo::ChannelMapping aidl) {
+    switch (aidl) {
+        case MicrophoneDynamicInfo::ChannelMapping::UNUSED:
+            return AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+        case MicrophoneDynamicInfo::ChannelMapping::DIRECT:
+            return AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
+        case MicrophoneDynamicInfo::ChannelMapping::PROCESSED:
+            return AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
+    }
+    return unexpected(BAD_VALUE);
+}
+ConversionResult<MicrophoneDynamicInfo::ChannelMapping>
+legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+        audio_microphone_channel_mapping_t legacy) {
+    switch (legacy) {
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED:
+            return MicrophoneDynamicInfo::ChannelMapping::UNUSED;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT:
+            return MicrophoneDynamicInfo::ChannelMapping::DIRECT;
+        case AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED:
+            return MicrophoneDynamicInfo::ChannelMapping::PROCESSED;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+        const MicrophoneInfo& aidlInfo, const MicrophoneDynamicInfo& aidlDynamic) {
+    static const audio_microphone_coordinate kCoordinateUnknown = {
+        AUDIO_MICROPHONE_COORDINATE_UNKNOWN, AUDIO_MICROPHONE_COORDINATE_UNKNOWN,
+        AUDIO_MICROPHONE_COORDINATE_UNKNOWN };
+    audio_microphone_characteristic_t legacy{};
+    if (aidlInfo.id != aidlDynamic.id) {
+        return unexpected(BAD_VALUE);
+    }
+    // Note: in the legacy structure, 'device_id' is the mic's ID, 'id' is APM port id.
+    RETURN_IF_ERROR(aidl2legacy_string(aidlInfo.id, legacy.device_id, AUDIO_MICROPHONE_ID_MAX_LEN));
+    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
+                    aidlInfo.device, &legacy.device, legacy.address));
+    legacy.location = VALUE_OR_RETURN(
+            aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(aidlInfo.location));
+    legacy.group = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_microphone_group_t(aidlInfo.group));
+    // For some reason, the legacy field is unsigned, however in the SDK layer it is signed,
+    // as it is in AIDL. So, use UINT_MAX for INDEX_IN_THE_GROUP_UNKNOWN which is -1.
+    if (aidlInfo.indexInTheGroup != MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN) {
+        legacy.index_in_the_group = VALUE_OR_RETURN(
+                convertReinterpret<unsigned int>(aidlInfo.indexInTheGroup));
+    } else {
+        legacy.index_in_the_group = UINT_MAX;
+    }
+    if (aidlInfo.sensitivity.has_value()) {
+        legacy.sensitivity = aidlInfo.sensitivity.value().leveldBFS;
+        legacy.max_spl = aidlInfo.sensitivity.value().maxSpldB;
+        legacy.min_spl = aidlInfo.sensitivity.value().minSpldB;
+    } else {
+        legacy.sensitivity = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+        legacy.max_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+        legacy.min_spl = AUDIO_MICROPHONE_SPL_UNKNOWN;
+    }
+    legacy.directionality = VALUE_OR_RETURN(
+            aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+                    aidlInfo.directionality));
+    if (aidlInfo.frequencyResponse.size() > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+        return unexpected(BAD_VALUE);
+    }
+    legacy.num_frequency_responses = 0;
+    for (const auto& p: aidlInfo.frequencyResponse) {
+        legacy.frequency_responses[0][legacy.num_frequency_responses] = p.frequencyHz;
+        legacy.frequency_responses[1][legacy.num_frequency_responses++] = p.leveldB;
+    }
+    if (aidlInfo.position.has_value()) {
+        legacy.geometric_location = VALUE_OR_RETURN(
+                aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+                        aidlInfo.position.value()));
+    } else {
+        legacy.geometric_location = kCoordinateUnknown;
+    }
+    if (aidlInfo.orientation.has_value()) {
+        legacy.orientation = VALUE_OR_RETURN(
+                aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+                        aidlInfo.orientation.value()));
+    } else {
+        legacy.orientation = kCoordinateUnknown;
+    }
+    if (aidlDynamic.channelMapping.size() > AUDIO_CHANNEL_COUNT_MAX) {
+        return unexpected(BAD_VALUE);
+    }
+    size_t i = 0;
+    for (; i < aidlDynamic.channelMapping.size(); ++i) {
+        legacy.channel_mapping[i] = VALUE_OR_RETURN(
+                aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+                        aidlDynamic.channelMapping[i]));
+    }
+    for (; i < AUDIO_CHANNEL_COUNT_MAX; ++i) {
+        legacy.channel_mapping[i] = AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED;
+    }
+    return legacy;
+}
+
+status_t
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+        const audio_microphone_characteristic_t& legacy,
+        MicrophoneInfo* aidlInfo, MicrophoneDynamicInfo* aidlDynamic) {
+    aidlInfo->id = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_string(legacy.device_id, AUDIO_MICROPHONE_ID_MAX_LEN));
+    aidlDynamic->id = aidlInfo->id;
+    aidlInfo->device = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_device_AudioDevice(
+                    legacy.device, legacy.address));
+    aidlInfo->location = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(legacy.location));
+    aidlInfo->group = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_microphone_group_t_int32_t(legacy.group));
+    // For some reason, the legacy field is unsigned, however in the SDK layer it is signed,
+    // as it is in AIDL. So, use UINT_MAX for INDEX_IN_THE_GROUP_UNKNOWN which is -1.
+    if (legacy.index_in_the_group != UINT_MAX) {
+        aidlInfo->indexInTheGroup = VALUE_OR_RETURN_STATUS(
+                convertReinterpret<int32_t>(legacy.index_in_the_group));
+    } else {
+        aidlInfo->indexInTheGroup = MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN;
+    }
+    if (legacy.sensitivity != AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN &&
+            legacy.max_spl != AUDIO_MICROPHONE_SPL_UNKNOWN &&
+            legacy.min_spl != AUDIO_MICROPHONE_SPL_UNKNOWN) {
+        MicrophoneInfo::Sensitivity sensitivity;
+        sensitivity.leveldBFS = legacy.sensitivity;
+        sensitivity.maxSpldB = legacy.max_spl;
+        sensitivity.minSpldB = legacy.min_spl;
+        aidlInfo->sensitivity = std::move(sensitivity);
+    } else {
+        aidlInfo->sensitivity = {};
+    }
+    aidlInfo->directionality = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+                    legacy.directionality));
+    if (legacy.num_frequency_responses > AUDIO_MICROPHONE_MAX_FREQUENCY_RESPONSES) {
+        return BAD_VALUE;
+    }
+    aidlInfo->frequencyResponse.resize(legacy.num_frequency_responses);
+    for (size_t i = 0; i < legacy.num_frequency_responses; ++i) {
+        aidlInfo->frequencyResponse[i].frequencyHz = legacy.frequency_responses[0][i];
+        aidlInfo->frequencyResponse[i].leveldB = legacy.frequency_responses[1][i];
+    }
+    if (legacy.geometric_location.x != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+            legacy.geometric_location.y != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+            legacy.geometric_location.z != AUDIO_MICROPHONE_COORDINATE_UNKNOWN) {
+        aidlInfo->position = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+                        legacy.geometric_location));
+    } else {
+        aidlInfo->position = {};
+    }
+    if (legacy.orientation.x != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+            legacy.orientation.y != AUDIO_MICROPHONE_COORDINATE_UNKNOWN &&
+            legacy.orientation.z != AUDIO_MICROPHONE_COORDINATE_UNKNOWN) {
+        aidlInfo->orientation = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+                        legacy.orientation));
+    } else {
+        aidlInfo->orientation = {};
+    }
+    size_t channelsUsed = AUDIO_CHANNEL_COUNT_MAX;
+    while (channelsUsed != 0 &&
+            legacy.channel_mapping[--channelsUsed] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {}
+    // Doing an increment is correct even when channel 0 is 'UNUSED',
+    // that's because AIDL requires to have at least 1 element in the mapping.
+    ++channelsUsed;
+    aidlDynamic->channelMapping.resize(channelsUsed);
+    for (size_t i = 0; i < channelsUsed; ++i) {
+        aidlDynamic->channelMapping[i] = VALUE_OR_RETURN_STATUS(
+                legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+                        legacy.channel_mapping[i]));
+    }
+    return OK;
+}
+
+}  // namespace android
+
+#if defined(BACKEND_NDK)
+}  // aidl
+#endif
diff --git a/media/audioaidlconversion/AidlConversionEffect.cpp b/media/audioaidlconversion/AidlConversionEffect.cpp
new file mode 100644
index 0000000..611cfab
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionEffect.cpp
@@ -0,0 +1,475 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <inttypes.h>
+#include <utility>
+
+#define LOG_TAG "AidlConversionEffect"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL NDK backend to legacy audio data structure conversion utilities.
+
+namespace aidl {
+namespace android {
+
+using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
+using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Downmix;
+using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::hardware::audio::effect::Visualizer;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+using ::android::status_t;
+using ::android::base::unexpected;
+using ::android::effect::utils::EffectParamReader;
+using ::android::effect::utils::EffectParamWriter;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Converters
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(Flags::Type type) {
+    switch (type) {
+        case Flags::Type::INSERT:
+            return EFFECT_FLAG_TYPE_INSERT;
+        case Flags::Type::AUXILIARY:
+            return EFFECT_FLAG_TYPE_AUXILIARY;
+        case Flags::Type::REPLACE:
+            return EFFECT_FLAG_TYPE_REPLACE;
+        case Flags::Type::PRE_PROC:
+            return EFFECT_FLAG_TYPE_PRE_PROC;
+        case Flags::Type::POST_PROC:
+            return EFFECT_FLAG_TYPE_POST_PROC;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Type> legacy2aidl_uint32_Flags_Type(uint32_t legacy) {
+    switch (legacy & EFFECT_FLAG_TYPE_MASK) {
+        case EFFECT_FLAG_TYPE_INSERT:
+            return Flags::Type::INSERT;
+        case EFFECT_FLAG_TYPE_AUXILIARY:
+            return Flags::Type::AUXILIARY;
+        case EFFECT_FLAG_TYPE_REPLACE:
+            return Flags::Type::REPLACE;
+        case EFFECT_FLAG_TYPE_PRE_PROC:
+            return Flags::Type::PRE_PROC;
+        case EFFECT_FLAG_TYPE_POST_PROC:
+            return Flags::Type::POST_PROC;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(Flags::Insert insert) {
+    switch (insert) {
+        case Flags::Insert::ANY:
+            return EFFECT_FLAG_INSERT_ANY;
+        case Flags::Insert::FIRST:
+            return EFFECT_FLAG_INSERT_FIRST;
+        case Flags::Insert::LAST:
+            return EFFECT_FLAG_INSERT_LAST;
+        case Flags::Insert::EXCLUSIVE:
+            return EFFECT_FLAG_INSERT_EXCLUSIVE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Insert> legacy2aidl_uint32_Flags_Insert(uint32_t legacy) {
+    switch (legacy & EFFECT_FLAG_INSERT_MASK) {
+        case EFFECT_FLAG_INSERT_ANY:
+            return Flags::Insert::ANY;
+        case EFFECT_FLAG_INSERT_FIRST:
+            return Flags::Insert::FIRST;
+        case EFFECT_FLAG_INSERT_LAST:
+            return Flags::Insert::LAST;
+        case EFFECT_FLAG_INSERT_EXCLUSIVE:
+            return Flags::Insert::EXCLUSIVE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(Flags::Volume volume) {
+    switch (volume) {
+        case Flags::Volume::NONE:
+            return 0;
+        case Flags::Volume::CTRL:
+            return EFFECT_FLAG_VOLUME_CTRL;
+        case Flags::Volume::IND:
+            return EFFECT_FLAG_VOLUME_IND;
+        case Flags::Volume::MONITOR:
+            return EFFECT_FLAG_VOLUME_MONITOR;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::Volume> legacy2aidl_uint32_Flags_Volume(uint32_t legacy) {
+    switch (legacy & EFFECT_FLAG_VOLUME_MASK) {
+        case EFFECT_FLAG_VOLUME_CTRL:
+            return Flags::Volume::CTRL;
+        case EFFECT_FLAG_VOLUME_IND:
+            return Flags::Volume::IND;
+        case EFFECT_FLAG_VOLUME_MONITOR:
+            return Flags::Volume::MONITOR;
+        case EFFECT_FLAG_VOLUME_NONE:
+            return Flags::Volume::NONE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_uint32(Flags aidl) {
+    uint32_t legacy = 0;
+    legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Type_uint32(aidl.type));
+    legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Insert_uint32(aidl.insert));
+    legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_Volume_uint32(aidl.volume));
+    legacy |= VALUE_OR_RETURN(aidl2legacy_Flags_HardwareAccelerator_uint32(aidl.hwAcceleratorMode));
+
+    if (aidl.offloadIndication) {
+        legacy |= EFFECT_FLAG_OFFLOAD_SUPPORTED;
+    }
+    if (aidl.deviceIndication) {
+        legacy |= EFFECT_FLAG_DEVICE_IND;
+    }
+    if (aidl.audioModeIndication) {
+        legacy |= EFFECT_FLAG_AUDIO_MODE_IND;
+    }
+    if (aidl.audioSourceIndication) {
+        legacy |= EFFECT_FLAG_AUDIO_SOURCE_IND;
+    }
+    if (aidl.bypass) {
+        legacy |= EFFECT_FLAG_NO_PROCESS;
+    }
+    return legacy;
+}
+
+ConversionResult<Flags> legacy2aidl_uint32_Flags(uint32_t legacy) {
+    Flags aidl;
+
+    aidl.type = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Type(legacy));
+    aidl.insert = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Insert(legacy));
+    aidl.volume = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_Volume(legacy));
+    aidl.hwAcceleratorMode = VALUE_OR_RETURN(legacy2aidl_uint32_Flags_HardwareAccelerator(legacy));
+    aidl.offloadIndication = (legacy & EFFECT_FLAG_OFFLOAD_SUPPORTED);
+    aidl.deviceIndication = (legacy & EFFECT_FLAG_DEVICE_IND);
+    aidl.audioModeIndication = (legacy & EFFECT_FLAG_AUDIO_MODE_IND);
+    aidl.audioSourceIndication = (legacy & EFFECT_FLAG_AUDIO_SOURCE_IND);
+    aidl.bypass = (legacy & EFFECT_FLAG_NO_PROCESS);
+    return aidl;
+}
+
+ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
+        Flags::HardwareAccelerator hwAcceleratorMode) {
+    switch (hwAcceleratorMode) {
+        case Flags::HardwareAccelerator::NONE:
+            return 0;
+        case Flags::HardwareAccelerator::SIMPLE:
+            return EFFECT_FLAG_HW_ACC_SIMPLE;
+        case Flags::HardwareAccelerator::TUNNEL:
+            return EFFECT_FLAG_HW_ACC_TUNNEL;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Flags::HardwareAccelerator> legacy2aidl_uint32_Flags_HardwareAccelerator(
+        uint32_t legacy) {
+    switch (legacy & EFFECT_FLAG_HW_ACC_MASK) {
+        case EFFECT_FLAG_HW_ACC_SIMPLE:
+            return Flags::HardwareAccelerator::SIMPLE;
+        case EFFECT_FLAG_HW_ACC_TUNNEL:
+            return Flags::HardwareAccelerator::TUNNEL;
+        case 0:
+            return Flags::HardwareAccelerator::NONE;
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<effect_descriptor_t>
+aidl2legacy_Descriptor_effect_descriptor(const Descriptor& aidl) {
+    effect_descriptor_t legacy;
+    legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.type));
+    legacy.uuid = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.common.id.uuid));
+    // legacy descriptor doesn't have proxy information
+    // proxy = VALUE_OR_RETURN(aidl2legacy_AudioUuid_audio_uuid_t(aidl.proxy));
+    legacy.apiVersion = EFFECT_CONTROL_API_VERSION;
+    legacy.flags = VALUE_OR_RETURN(aidl2legacy_Flags_uint32(aidl.common.flags));
+    legacy.cpuLoad = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.cpuLoad));
+    legacy.memoryUsage = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.common.memoryUsage));
+    RETURN_IF_ERROR(aidl2legacy_string(aidl.common.name, legacy.name, sizeof(legacy.name)));
+    RETURN_IF_ERROR(aidl2legacy_string(aidl.common.implementor, legacy.implementor,
+                                        sizeof(legacy.implementor)));
+    return legacy;
+}
+
+ConversionResult<Descriptor>
+legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& legacy) {
+    Descriptor aidl;
+    aidl.common.id.type = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.type));
+    aidl.common.id.uuid = VALUE_OR_RETURN(legacy2aidl_audio_uuid_t_AudioUuid(legacy.uuid));
+    // legacy descriptor doesn't have proxy information
+    // aidl.common.id.proxy
+    aidl.common.flags = VALUE_OR_RETURN(legacy2aidl_uint32_Flags(legacy.flags));
+    aidl.common.cpuLoad = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.cpuLoad));
+    aidl.common.memoryUsage = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.memoryUsage));
+    aidl.common.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
+    aidl.common.implementor =
+            VALUE_OR_RETURN(legacy2aidl_string(legacy.implementor, sizeof(legacy.implementor)));
+    return aidl;
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(const Parameter& aidl) {
+    int echoDelay = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, AcousticEchoCanceler, acousticEchoCanceler,
+                                         AcousticEchoCanceler::echoDelayUs, int));
+    return VALUE_OR_RETURN(convertReinterpret<uint32_t>(echoDelay));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy) {
+    int delay = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy));
+    return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, echoDelayUs, delay);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(const Parameter& aidl) {
+    bool mobileMode = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, AcousticEchoCanceler, acousticEchoCanceler,
+                                         AcousticEchoCanceler::mobileMode, bool));
+    return VALUE_OR_RETURN(convertIntegral<uint32_t>(mobileMode));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy) {
+    bool mode = VALUE_OR_RETURN(convertIntegral<bool>(legacy));
+    return MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, mobileMode, mode);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
+        const Parameter& aidl) {
+    int gain = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControlV2, automaticGainControlV2,
+                                         AutomaticGainControlV2::fixedDigitalGainMb, int));
+    return VALUE_OR_RETURN(convertReinterpret<uint32_t>(gain));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy) {
+    int gain = VALUE_OR_RETURN(convertReinterpret<int>(legacy));
+    return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+                                   fixedDigitalGainMb, gain);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
+        const Parameter& aidl) {
+    const auto& le = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
+            aidl, AutomaticGainControlV2, automaticGainControlV2,
+            AutomaticGainControlV2::levelEstimator, AutomaticGainControlV2::LevelEstimator));
+    return static_cast<uint32_t>(le);
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy) {
+    if (legacy > (uint32_t)AutomaticGainControlV2::LevelEstimator::PEAK) {
+        return unexpected(BAD_VALUE);
+    }
+    AutomaticGainControlV2::LevelEstimator le =
+            static_cast<AutomaticGainControlV2::LevelEstimator>(legacy);
+    return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2, levelEstimator,
+                                   le);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
+        const Parameter& aidl) {
+    int saturationMargin = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, AutomaticGainControlV2, automaticGainControlV2,
+                                         AutomaticGainControlV2::saturationMarginMb, int));
+    return VALUE_OR_RETURN(convertIntegral<uint32_t>(saturationMargin));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy) {
+    int saturationMargin = VALUE_OR_RETURN(convertIntegral<int>(legacy));
+    return MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+                                   saturationMarginMb, saturationMargin);
+}
+
+ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
+        const Parameter& aidl) {
+    int strength = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, BassBoost, bassBoost, BassBoost::strengthPm, int));
+    return VALUE_OR_RETURN(convertIntegral<uint16_t>(strength));
+}
+
+ConversionResult<Parameter> legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy) {
+    int strength = VALUE_OR_RETURN(convertIntegral<int>(legacy));
+    return MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, strengthPm, strength);
+}
+
+ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(const Parameter& aidl) {
+    Downmix::Type aidlType = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, Downmix::type, Downmix::Type));
+    return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
+}
+
+ConversionResult<Parameter> legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy) {
+    if (legacy > (uint32_t) Downmix::Type::FOLD) {
+        return unexpected(BAD_VALUE);
+    }
+    Downmix::Type aidlType = static_cast<Downmix::Type>(legacy);
+    return MAKE_SPECIFIC_PARAMETER(Downmix, downmix, type, aidlType);
+}
+
+ConversionResult<int16_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_uint32_(
+        const Parameter& aidl) {
+    Downmix::Type aidlType = VALUE_OR_RETURN(
+            GET_PARAMETER_SPECIFIC_FIELD(aidl, Downmix, downmix, Downmix::type, Downmix::Type));
+    return VALUE_OR_RETURN(convertIntegral<int16_t>(static_cast<uint32_t>(aidlType)));
+}
+
+ConversionResult<DynamicsProcessing::ResolutionPreference>
+legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(int32_t legacy) {
+    if (legacy > (int32_t)DynamicsProcessing::ResolutionPreference::FAVOR_TIME_RESOLUTION) {
+        return unexpected(BAD_VALUE);
+    }
+    return static_cast<DynamicsProcessing::ResolutionPreference>(legacy);
+}
+
+ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+        DynamicsProcessing::ResolutionPreference aidl) {
+    return static_cast<int32_t>(aidl);
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+        Visualizer::ScalingMode aidl) {
+    switch (aidl) {
+        case Visualizer::ScalingMode::NORMALIZED: {
+            return 0;
+        }
+        case Visualizer::ScalingMode::AS_PLAYED: {
+            return 1;
+        }
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::ScalingMode> legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(
+        uint32_t legacy) {
+    if (legacy == 0) {
+        return Visualizer::ScalingMode::NORMALIZED;
+    } else if (legacy == 1) {
+        return Visualizer::ScalingMode::AS_PLAYED;
+    } else {
+        return unexpected(BAD_VALUE);
+    }
+}
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+        Visualizer::MeasurementMode aidl) {
+    switch (aidl) {
+        case Visualizer::MeasurementMode::NONE: {
+            return 0;
+        }
+        case Visualizer::MeasurementMode::PEAK_RMS: {
+            return 1;
+        }
+    }
+    return unexpected(BAD_VALUE);
+}
+
+ConversionResult<Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy) {
+    if (legacy == 0) {
+        return Visualizer::MeasurementMode::NONE;
+    } else if (legacy == 1) {
+        return Visualizer::MeasurementMode::PEAK_RMS;
+    } else {
+        return unexpected(BAD_VALUE);
+    }
+}
+
+/**
+ * Copy the parameter area of effect_param_t to DefaultExtension::bytes.
+ */
+ConversionResult<VendorExtension> legacy2aidl_EffectParameterReader_Param_VendorExtension(
+        EffectParamReader& param) {
+    size_t len = param.getParameterSize();
+    DefaultExtension defaultExt;
+    defaultExt.bytes.resize(len);
+    RETURN_IF_ERROR(param.readFromParameter(defaultExt.bytes.data(), len));
+
+    VendorExtension ext;
+    ext.extension.setParcelable(defaultExt);
+    return ext;
+}
+
+/**
+ * Copy the data area of effect_param_t to DefaultExtension::bytes.
+ */
+ConversionResult<VendorExtension> legacy2aidl_EffectParameterReader_Data_VendorExtension(
+        EffectParamReader& param) {
+    size_t len = param.getValueSize();
+    DefaultExtension defaultExt;
+    defaultExt.bytes.resize(len);
+    RETURN_IF_ERROR(param.readFromValue(defaultExt.bytes.data(), len));
+
+    VendorExtension ext;
+    ext.extension.setParcelable(defaultExt);
+    return ext;
+}
+
+/**
+ * Copy DefaultExtension::bytes to the data area of effect_param_t.
+ */
+ConversionResult<status_t> aidl2legacy_VendorExtension_EffectParameterWriter_Data(
+        EffectParamWriter& param, VendorExtension ext) {
+    std::optional<DefaultExtension> defaultExt;
+    RETURN_IF_ERROR(ext.extension.getParcelable(&defaultExt));
+    if (!defaultExt.has_value()) {
+        return unexpected(BAD_VALUE);
+    }
+
+    RETURN_IF_ERROR(param.writeToValue(defaultExt->bytes.data(), defaultExt->bytes.size()));
+
+    return OK;
+}
+
+ConversionResult<Parameter> legacy2aidl_EffectParameterReader_ParameterExtension(
+        EffectParamReader& param) {
+    VendorExtension ext =
+            VALUE_OR_RETURN(legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+    return UNION_MAKE(Parameter, specific, UNION_MAKE(Parameter::Specific, vendorEffect, ext));
+}
+
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+        EffectParamWriter& legacy) {
+    VendorExtension ext = VALUE_OR_RETURN(
+            (::aidl::android::getParameterSpecific<Parameter, VendorExtension,
+                                                   Parameter::Specific::vendorEffect>(aidl)));
+    return VALUE_OR_RETURN_STATUS(
+            aidl2legacy_VendorExtension_EffectParameterWriter_Data(legacy, ext));
+}
+
+}  // namespace android
+}  // aidl
diff --git a/media/audioaidlconversion/AidlConversionNdk.cpp b/media/audioaidlconversion/AidlConversionNdk.cpp
new file mode 100644
index 0000000..71c547c
--- /dev/null
+++ b/media/audioaidlconversion/AidlConversionNdk.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <utility>
+
+#include <system/audio.h>
+#define LOG_TAG "AidlConversionNdk"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <Utils.h>
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// AIDL NDK backend to legacy audio data structure conversion utilities.
+
+namespace aidl {
+namespace android {
+
+using hardware::audio::common::PlaybackTrackMetadata;
+using hardware::audio::common::RecordTrackMetadata;
+using ::android::BAD_VALUE;
+using ::android::OK;
+
+namespace {
+
+::android::status_t combineString(
+        const std::vector<std::string>& v, char separator, std::string* result) {
+    std::ostringstream oss;
+    for (const auto& s : v) {
+        if (oss.tellp() > 0) {
+            oss << separator;
+        }
+        if (s.find(separator) == std::string::npos) {
+            oss << s;
+        } else {
+            ALOGE("%s: string \"%s\" contains separator character \"%c\"",
+                    __func__, s.c_str(), separator);
+            return BAD_VALUE;
+        }
+    }
+    *result = oss.str();
+    return OK;
+}
+
+std::vector<std::string> splitString(const std::string& s, char separator) {
+    std::istringstream iss(s);
+    std::string t;
+    std::vector<std::string> result;
+    while (std::getline(iss, t, separator)) {
+        result.push_back(std::move(t));
+    }
+    return result;
+}
+
+std::vector<std::string> filterOutNonVendorTags(const std::vector<std::string>& tags) {
+    std::vector<std::string> result;
+    std::copy_if(tags.begin(), tags.end(), std::back_inserter(result),
+            ::aidl::android::hardware::audio::common::maybeVendorExtension);
+    return result;
+}
+
+}  // namespace
+
+// buffer_provider_t is not supported thus skipped
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
+        const media::audio::common::AudioConfigBase& aidl, bool isInput) {
+    buffer_config_t legacy;
+
+    legacy.samplingRate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
+    legacy.mask |= EFFECT_CONFIG_SMP_RATE;
+
+    legacy.channels = VALUE_OR_RETURN(
+            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
+    legacy.mask |= EFFECT_CONFIG_CHANNELS;
+
+    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
+    legacy.mask |= EFFECT_CONFIG_FORMAT;
+
+    // TODO: add accessMode and mask
+    return legacy;
+}
+
+ConversionResult<media::audio::common::AudioConfigBase>
+legacy2aidl_buffer_config_t_AudioConfigBase(const buffer_config_t& legacy, bool isInput) {
+    media::audio::common::AudioConfigBase aidl;
+
+    if (legacy.mask & EFFECT_CONFIG_SMP_RATE) {
+        aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.samplingRate));
+    }
+    if (legacy.mask & EFFECT_CONFIG_CHANNELS) {
+        aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                static_cast<audio_channel_mask_t>(legacy.channels), isInput));
+    }
+    if (legacy.mask & EFFECT_CONFIG_FORMAT) {
+        aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(
+                static_cast<audio_format_t>(legacy.format)));
+    }
+
+    // TODO: add accessMode and mask
+    return aidl;
+}
+
+::android::status_t aidl2legacy_AudioAttributesTags(
+        const std::vector<std::string>& aidl, char* legacy) {
+    std::string aidlTags;
+    RETURN_STATUS_IF_ERROR(combineString(
+                    filterOutNonVendorTags(aidl), AUDIO_ATTRIBUTES_TAGS_SEPARATOR, &aidlTags));
+    RETURN_STATUS_IF_ERROR(aidl2legacy_string(aidlTags, legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
+    return OK;
+}
+
+ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy) {
+    std::string legacyTags = VALUE_OR_RETURN(legacy2aidl_string(
+                    legacy, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE));
+    return filterOutNonVendorTags(splitString(legacyTags, AUDIO_ATTRIBUTES_TAGS_SEPARATOR));
+}
+
+ConversionResult<playback_track_metadata_v7>
+aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(const PlaybackTrackMetadata& aidl) {
+    playback_track_metadata_v7 legacy;
+    legacy.base.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
+    legacy.base.content_type = VALUE_OR_RETURN(aidl2legacy_AudioContentType_audio_content_type_t(
+                    aidl.contentType));
+    legacy.base.gain = aidl.gain;
+    legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                    aidl.channelMask, false /*isInput*/));
+    RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
+    return legacy;
+}
+
+ConversionResult<PlaybackTrackMetadata>
+legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
+        const playback_track_metadata_v7& legacy) {
+    PlaybackTrackMetadata aidl;
+    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.base.usage));
+    aidl.contentType = VALUE_OR_RETURN(legacy2aidl_audio_content_type_t_AudioContentType(
+                    legacy.base.content_type));
+    aidl.gain = legacy.base.gain;
+    aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                    legacy.channel_mask, false /*isInput*/));
+    aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
+    return aidl;
+}
+
+ConversionResult<record_track_metadata_v7>
+aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(const RecordTrackMetadata& aidl) {
+    record_track_metadata_v7 legacy;
+    legacy.base.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(aidl.source));
+    legacy.base.gain = aidl.gain;
+    if (aidl.destinationDevice.has_value()) {
+        RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(aidl.destinationDevice.value(),
+                        &legacy.base.dest_device, legacy.base.dest_device_address));
+    } else {
+        legacy.base.dest_device = AUDIO_DEVICE_NONE;
+    }
+    legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+                    aidl.channelMask, true /*isInput*/));
+    RETURN_IF_ERROR(aidl2legacy_AudioAttributesTags(aidl.tags, legacy.tags));
+    return legacy;
+}
+
+ConversionResult<RecordTrackMetadata>
+legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy) {
+    RecordTrackMetadata aidl;
+    aidl.source = VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.base.source));
+    aidl.gain = legacy.base.gain;
+    if (legacy.base.dest_device != AUDIO_DEVICE_NONE) {
+        aidl.destinationDevice = VALUE_OR_RETURN(legacy2aidl_audio_device_AudioDevice(
+                        legacy.base.dest_device, legacy.base.dest_device_address));
+    }
+    aidl.channelMask = VALUE_OR_RETURN(legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                    legacy.channel_mask, true /*isInput*/));
+    aidl.tags = VALUE_OR_RETURN(legacy2aidl_AudioAttributesTags(legacy.tags));
+    return aidl;
+}
+
+}  // namespace android
+}  // aidl
diff --git a/media/audioaidlconversion/Android.bp b/media/audioaidlconversion/Android.bp
new file mode 100644
index 0000000..bdb3a2c
--- /dev/null
+++ b/media/audioaidlconversion/Android.bp
@@ -0,0 +1,183 @@
+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"],
+}
+
+cc_defaults {
+    name: "audio_aidl_conversion_common_util_default",
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    min_sdk_version: "29",
+    export_include_dirs: [
+        "include",
+    ],
+    header_libs: [
+        "libbase_headers",
+        "liberror_headers",
+    ],
+    export_header_lib_headers: [
+        "libbase_headers",
+        "liberror_headers",
+    ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.btservices",
+        "com.android.media",
+        "com.android.media.swcodec",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+// This is intended for clients needing to include AidlConversionUtil.h, without extra dependencies.
+cc_library_headers {
+    name: "libaudio_aidl_conversion_common_util_cpp",
+    defaults: [
+        "audio_aidl_conversion_common_util_default",
+    ],
+}
+
+cc_library_headers {
+    name: "libaudio_aidl_conversion_common_util_ndk",
+    defaults: [
+        "audio_aidl_conversion_common_util_default",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+}
+
+cc_defaults {
+    name: "audio_aidl_conversion_common_default",
+    export_include_dirs: ["include"],
+    host_supported: true,
+    vendor_available: true,
+    double_loadable: true,
+    header_libs: [
+        "libaudio_system_headers",
+        "libhardware_headers",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libshmemcompat",
+        "libstagefright_foundation",
+        "libutils",
+        "shared-file-region-aidl-cpp",
+        "framework-permission-aidl-cpp",
+    ],
+    export_shared_lib_headers: [
+        "libbase",
+        "shared-file-region-aidl-cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+    ],
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+/**
+ * Only AIDL CPP backend conversion supported.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_common_cpp",
+    srcs: [
+        "AidlConversionCppNdk.cpp",
+    ],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_cpp",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_cpp",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_media_audio_common_types_cpp_export_shared",
+    ],
+    min_sdk_version: "29",
+}
+
+/**
+ * Only AIDL NDK backend conversion supported.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_common_ndk",
+    srcs: [
+        "AidlConversionCppNdk.cpp",
+        "AidlConversionNdk.cpp",
+    ],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_hardware_audio_common_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libbase",
+    ],
+    static_libs: [
+        "libaudioaidlcommon",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+    min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
+
+/**
+ * Only including AIDL effect HAL conversion.
+ */
+cc_library {
+    name: "libaudio_aidl_conversion_effect_ndk",
+    srcs: [
+        "AidlConversionEffect.cpp",
+    ],
+    header_libs: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    export_header_lib_headers: [
+        "libaudio_aidl_conversion_common_util_ndk",
+    ],
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_hardware_audio_common_ndk_shared",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    shared_libs: [
+        "libaudio_aidl_conversion_common_ndk",
+        "libbinder_ndk",
+        "libbase",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+    min_sdk_version: "31", //AParcelableHolder has been introduced in 31
+}
diff --git a/media/audioaidlconversion/TEST_MAPPING b/media/audioaidlconversion/TEST_MAPPING
new file mode 100644
index 0000000..a0c9759
--- /dev/null
+++ b/media/audioaidlconversion/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "audio_aidl_ndk_conversion_tests"
+    }
+  ]
+}
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
new file mode 100644
index 0000000..9100892
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk-impl.h
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// WARNING: This file is intended for multiple inclusion.
+// Do not include directly, use 'AidlConversionCppNdk.h'.
+#if (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_NDK)) || \
+    (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_CPP))
+#if defined(BACKEND_NDK_IMPL)
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_NDK
+#else
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_CPP
+#endif  // BACKEND_NDK_IMPL
+
+#include <limits>
+#include <type_traits>
+
+/**
+ * Can handle conversion between AIDL (both CPP and NDK backend) and legacy type.
+ * Controlled by the cflags preprocessor in Android.bp.
+ */
+#if defined(BACKEND_NDK_IMPL)
+#define PREFIX(f) <aidl/f>
+#else
+#define PREFIX(f) <f>
+#endif
+
+#include PREFIX(android/media/audio/common/AudioChannelLayout.h)
+#include PREFIX(android/media/audio/common/AudioConfig.h)
+#include PREFIX(android/media/audio/common/AudioConfigBase.h)
+#include PREFIX(android/media/audio/common/AudioContentType.h)
+#include PREFIX(android/media/audio/common/AudioDeviceDescription.h)
+#include PREFIX(android/media/audio/common/AudioDualMonoMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMetadataType.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationMode.h)
+#include PREFIX(android/media/audio/common/AudioEncapsulationType.h)
+#include PREFIX(android/media/audio/common/AudioFormatDescription.h)
+#include PREFIX(android/media/audio/common/AudioGain.h)
+#include PREFIX(android/media/audio/common/AudioGainConfig.h)
+#include PREFIX(android/media/audio/common/AudioGainMode.h)
+#include PREFIX(android/media/audio/common/AudioInputFlags.h)
+#include PREFIX(android/media/audio/common/AudioIoFlags.h)
+#include PREFIX(android/media/audio/common/AudioLatencyMode.h)
+#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/AudioPort.h)
+#include PREFIX(android/media/audio/common/AudioPortConfig.h)
+#include PREFIX(android/media/audio/common/AudioPortExt.h)
+#include PREFIX(android/media/audio/common/AudioPortMixExt.h)
+#include PREFIX(android/media/audio/common/AudioPlaybackRate.h)
+#include PREFIX(android/media/audio/common/AudioProfile.h)
+#include PREFIX(android/media/audio/common/AudioSource.h)
+#include PREFIX(android/media/audio/common/AudioStandard.h)
+#include PREFIX(android/media/audio/common/AudioUsage.h)
+#include PREFIX(android/media/audio/common/AudioUuid.h)
+#include PREFIX(android/media/audio/common/ExtraAudioDescriptor.h)
+#include PREFIX(android/media/audio/common/Int.h)
+#include PREFIX(android/media/audio/common/MicrophoneDynamicInfo.h)
+#include PREFIX(android/media/audio/common/MicrophoneInfo.h)
+#undef PREFIX
+
+#include <system/audio.h>
+#include <system/audio_effect.h>
+
+#if defined(BACKEND_NDK_IMPL)
+namespace aidl {
+#endif
+
+namespace android {
+
+// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
+// the string.
+::android::status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
+ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
+
+ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
+
+ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
+
+ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
+
+ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
+
+ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
+
+ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
+
+ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
+
+ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
+
+ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
+
+ConversionResult<::android::String8> aidl2legacy_string_view_String8(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String8_string(const ::android::String8& legacy);
+
+ConversionResult<::android::String16> aidl2legacy_string_view_String16(std::string_view aidl);
+ConversionResult<std::string> legacy2aidl_String16_string(const ::android::String16& legacy);
+
+ConversionResult<std::optional<::android::String16>>
+aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
+ConversionResult<std::optional<std::string_view>>
+legacy2aidl_optional_String16_optional_string(std::optional<::android::String16> legacy);
+
+ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
+        const media::audio::common::AudioChannelLayout& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioChannelLayout>
+legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
+
+audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+        int aidlLayout, bool isInput);
+int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
+        audio_channel_mask_t legacy, bool isInput);
+
+enum class AudioPortDirection {
+    INPUT, OUTPUT
+};
+ConversionResult<AudioPortDirection> portDirection(audio_port_role_t role, audio_port_type_t type);
+ConversionResult<audio_port_role_t> portRole(AudioPortDirection direction, audio_port_type_t type);
+
+ConversionResult<audio_config_t>
+aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfig>
+legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
+
+ConversionResult<audio_config_base_t>
+aidl2legacy_AudioConfigBase_audio_config_base_t(
+        const media::audio::common::AudioConfigBase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfigBase>
+legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
+        int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
+        audio_input_flags_t legacy);
+
+ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
+        int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
+        audio_output_flags_t legacy);
+
+ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
+        const media::audio::common::AudioIoFlags& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
+        const audio_io_flags& legacy, bool isInput);
+
+ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
+
+ConversionResult<audio_content_type_t>
+aidl2legacy_AudioContentType_audio_content_type_t(
+        media::audio::common::AudioContentType aidl);
+ConversionResult<media::audio::common::AudioContentType>
+legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
+
+ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
+        const media::audio::common::AudioDeviceDescription& aidl);
+ConversionResult<media::audio::common::AudioDeviceDescription>
+legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
+
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+        char* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+        ::android::String8* legacyAddress);
+::android::status_t aidl2legacy_AudioDevice_audio_device(
+        const media::audio::common::AudioDevice& aidl, audio_devices_t* legacyType,
+        std::string* legacyAddress);
+
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const char* legacyAddress);
+ConversionResult<media::audio::common::AudioDevice> legacy2aidl_audio_device_AudioDevice(
+        audio_devices_t legacyType, const ::android::String8& legacyAddress);
+
+ConversionResult<audio_extra_audio_descriptor>
+aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
+        const media::audio::common::ExtraAudioDescriptor& aidl);
+
+ConversionResult<media::audio::common::ExtraAudioDescriptor>
+legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
+        const audio_extra_audio_descriptor& legacy);
+
+ConversionResult<audio_encapsulation_metadata_type_t>
+aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
+        media::audio::common::AudioEncapsulationMetadataType aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
+legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+        audio_encapsulation_metadata_type_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_mode_t>
+aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
+        media::audio::common::AudioEncapsulationMode aidl);
+ConversionResult<media::audio::common::AudioEncapsulationMode>
+legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
+
+ConversionResult<audio_encapsulation_type_t>
+aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
+        const media::audio::common::AudioEncapsulationType& aidl);
+ConversionResult<media::audio::common::AudioEncapsulationType>
+legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
+        const audio_encapsulation_type_t& legacy);
+
+ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
+        const media::audio::common::AudioFormatDescription& aidl);
+ConversionResult<media::audio::common::AudioFormatDescription>
+legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
+
+ConversionResult<audio_gain_mode_t>
+aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
+ConversionResult<media::audio::common::AudioGainMode>
+legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
+
+ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
+        const media::audio::common::AudioGainConfig& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGainConfig>
+legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
+
+ConversionResult<audio_gain>
+aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioGain>
+legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
+
+ConversionResult<audio_input_flags_t>
+aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
+ConversionResult<media::audio::common::AudioInputFlags>
+legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
+
+ConversionResult<audio_mode_t>
+aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
+ConversionResult<media::audio::common::AudioMode>
+legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+
+ConversionResult<audio_offload_info_t>
+aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
+        const media::audio::common::AudioOffloadInfo& aidl);
+ConversionResult<media::audio::common::AudioOffloadInfo>
+legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
+
+ConversionResult<audio_output_flags_t>
+aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
+ConversionResult<media::audio::common::AudioOutputFlags>
+legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
+
+// This type is unnamed in the original definition, thus we name it here.
+using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
+ConversionResult<audio_port_config_mix_ext_usecase>
+aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+        const media::audio::common::AudioPortMixExtUseCase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioPortMixExtUseCase>
+legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+        const audio_port_config_mix_ext_usecase& legacy, bool isInput);
+
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+        const media::audio::common::AudioPortDeviceExt& aidl);
+ConversionResult<media::audio::common::AudioPortDeviceExt>
+        legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+        const audio_port_config_device_ext& legacy);
+
+::android::status_t aidl2legacy_AudioPortConfig_audio_port_config(
+        const media::audio::common::AudioPortConfig& aidl, bool isInput,
+        audio_port_config* legacy, int32_t* portId);
+ConversionResult<media::audio::common::AudioPortConfig>
+legacy2aidl_audio_port_config_AudioPortConfig(
+        const audio_port_config& legacy, bool isInput, int32_t portId);
+
+ConversionResult<audio_port_mix_ext> aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
+        const media::audio::common::AudioPortMixExt& aidl);
+ConversionResult<media::audio::common::AudioPortMixExt>
+legacy2aidl_audio_port_mix_ext_AudioPortMixExt(
+        const audio_port_mix_ext& legacy);
+
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+        const media::audio::common::AudioPortDeviceExt& aidl);
+ConversionResult<media::audio::common::AudioPortDeviceExt>
+legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+        const audio_port_device_ext& legacy);
+
+ConversionResult<audio_port_v7>
+aidl2legacy_AudioPort_audio_port_v7(
+        const media::audio::common::AudioPort& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioPort>
+legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy, bool isInput);
+
+ConversionResult<audio_profile> aidl2legacy_AudioProfile_audio_profile(
+        const media::audio::common::AudioProfile& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioProfile> legacy2aidl_audio_profile_AudioProfile(
+        const audio_profile& legacy, bool isInput);
+
+ConversionResult<audio_standard_t> aidl2legacy_AudioStandard_audio_standard_t(
+        media::audio::common::AudioStandard aidl);
+ConversionResult<media::audio::common::AudioStandard> legacy2aidl_audio_standard_t_AudioStandard(
+        audio_standard_t legacy);
+
+ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
+        media::audio::common::AudioSource aidl);
+ConversionResult<media::audio::common::AudioSource> legacy2aidl_audio_source_t_AudioSource(
+        audio_source_t legacy);
+
+ConversionResult<audio_usage_t> aidl2legacy_AudioUsage_audio_usage_t(
+        media::audio::common::AudioUsage aidl);
+ConversionResult<media::audio::common::AudioUsage> legacy2aidl_audio_usage_t_AudioUsage(
+        audio_usage_t legacy);
+
+ConversionResult<audio_uuid_t> aidl2legacy_AudioUuid_audio_uuid_t(
+        const media::audio::common::AudioUuid &aidl);
+ConversionResult<media::audio::common::AudioUuid> legacy2aidl_audio_uuid_t_AudioUuid(
+        const audio_uuid_t& legacy);
+
+ConversionResult<audio_dual_mono_mode_t>
+aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::audio::common::AudioDualMonoMode aidl);
+ConversionResult<media::audio::common::AudioDualMonoMode>
+legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
+
+ConversionResult<audio_timestretch_fallback_mode_t>
+aidl2legacy_TimestretchFallbackMode_audio_timestretch_fallback_mode_t(
+        media::audio::common::AudioPlaybackRate::TimestretchFallbackMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchFallbackMode>
+legacy2aidl_audio_timestretch_fallback_mode_t_TimestretchFallbackMode(
+        audio_timestretch_fallback_mode_t legacy);
+
+ConversionResult<audio_timestretch_stretch_mode_t>
+aidl2legacy_TimestretchMode_audio_timestretch_stretch_mode_t(
+        media::audio::common::AudioPlaybackRate::TimestretchMode aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate::TimestretchMode>
+legacy2aidl_audio_timestretch_stretch_mode_t_TimestretchMode(
+        audio_timestretch_stretch_mode_t legacy);
+
+ConversionResult<audio_playback_rate_t>
+aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(
+        const media::audio::common::AudioPlaybackRate& aidl);
+ConversionResult<media::audio::common::AudioPlaybackRate>
+legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
+
+ConversionResult<audio_latency_mode_t>
+aidl2legacy_AudioLatencyMode_audio_latency_mode_t(media::audio::common::AudioLatencyMode aidl);
+ConversionResult<media::audio::common::AudioLatencyMode>
+legacy2aidl_audio_latency_mode_t_AudioLatencyMode(audio_latency_mode_t legacy);
+
+ConversionResult<audio_microphone_location_t>
+aidl2legacy_MicrophoneInfoLocation_audio_microphone_location_t(
+        media::audio::common::MicrophoneInfo::Location aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Location>
+legacy2aidl_audio_microphone_location_t_MicrophoneInfoLocation(audio_microphone_location_t legacy);
+
+ConversionResult<audio_microphone_group_t> aidl2legacy_int32_t_audio_microphone_group_t(
+        int32_t aidl);
+ConversionResult<int32_t> legacy2aidl_audio_microphone_group_t_int32_t(
+        audio_microphone_group_t legacy);
+
+ConversionResult<audio_microphone_directionality_t>
+aidl2legacy_MicrophoneInfoDirectionality_audio_microphone_directionality_t(
+        media::audio::common::MicrophoneInfo::Directionality aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Directionality>
+legacy2aidl_audio_microphone_directionality_t_MicrophoneInfoDirectionality(
+        audio_microphone_directionality_t legacy);
+
+ConversionResult<audio_microphone_coordinate>
+aidl2legacy_MicrophoneInfoCoordinate_audio_microphone_coordinate(
+        const media::audio::common::MicrophoneInfo::Coordinate& aidl);
+ConversionResult<media::audio::common::MicrophoneInfo::Coordinate>
+legacy2aidl_audio_microphone_coordinate_MicrophoneInfoCoordinate(
+        const audio_microphone_coordinate& legacy);
+
+ConversionResult<audio_microphone_channel_mapping_t>
+aidl2legacy_MicrophoneDynamicInfoChannelMapping_audio_microphone_channel_mapping_t(
+        media::audio::common::MicrophoneDynamicInfo::ChannelMapping aidl);
+ConversionResult<media::audio::common::MicrophoneDynamicInfo::ChannelMapping>
+legacy2aidl_audio_microphone_channel_mapping_t_MicrophoneDynamicInfoChannelMapping(
+        audio_microphone_channel_mapping_t legacy);
+
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+        const media::audio::common::MicrophoneInfo& aidlInfo,
+        const media::audio::common::MicrophoneDynamicInfo& aidlDynamic);
+::android::status_t
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+        const audio_microphone_characteristic_t& legacy,
+        media::audio::common::MicrophoneInfo* aidlInfo,
+        media::audio::common::MicrophoneDynamicInfo* aidlDynamic);
+
+}  // namespace android
+
+#if defined(BACKEND_NDK_IMPL)
+} // aidl
+#endif
+
+// (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_NDK)) || \
+// (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_CPP_NDK_CPP))
+#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionCppNdk.h b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
new file mode 100644
index 0000000..ea168a4
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionCppNdk.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// Since conversion functions use ConversionResult, pull it in here.
+#include <media/AidlConversionUtil.h>
+
+// Include 'AidlConversionCppNdk.h' once if 'BACKEND_NDK' is defined,
+// or no 'BACKEND_*' is defined (C++ backend). Include twice if
+// 'BACKEND_CPP_NDK' is defined: once with 'BACKEND_NDK_IMPL', once w/o defines.
+
+#if defined(BACKEND_CPP_NDK) || defined(BACKEND_NDK)
+#define BACKEND_NDK_IMPL
+#include <media/AidlConversionCppNdk-impl.h>
+#undef BACKEND_NDK_IMPL
+#endif
+
+#if defined(BACKEND_CPP_NDK) || !defined(BACKEND_NDK)
+#include <media/AidlConversionCppNdk-impl.h>
+#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionEffect.h b/media/audioaidlconversion/include/media/AidlConversionEffect.h
new file mode 100644
index 0000000..5e245a7
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionEffect.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy type.
+ */
+#include <hardware/audio_effect.h>
+#include <media/AidlConversionUtil.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/audio_effects_utils.h>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+
+namespace aidl {
+namespace android {
+
+template <typename P, typename T, typename P::Specific::Tag tag>
+ConversionResult<T> getParameterSpecific(const P& u) {
+    const auto& spec = VALUE_OR_RETURN(UNION_GET(u, specific));
+    return unionGetField<typename P::Specific, tag>(spec);
+}
+
+template <typename P, typename T, typename P::Specific::Tag tag, typename T::Tag field, typename F>
+ConversionResult<F> getParameterSpecificField(const P& u) {
+    const auto& spec =
+            VALUE_OR_RETURN((getParameterSpecific<std::decay_t<decltype(u)>, T, tag>(u)));
+    return VALUE_OR_RETURN((unionGetField<T, field>(spec)));
+}
+
+#define GET_PARAMETER_SPECIFIC_FIELD(_u, _effect, _tag, _field, _fieldType)                      \
+    getParameterSpecificField<std::decay_t<decltype(_u)>, _effect,                               \
+                              aidl::android::hardware::audio::effect::Parameter::Specific::_tag, \
+                              _effect::_field, _fieldType>(_u)
+
+#define MAKE_SPECIFIC_PARAMETER(_spec, _tag, _field, _value)                                 \
+    UNION_MAKE(aidl::android::hardware::audio::effect::Parameter, specific,                  \
+               UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Specific, _tag, \
+                          UNION_MAKE(_spec, _field, _value)))
+
+#define MAKE_SPECIFIC_PARAMETER_ID(_spec, _tag, _field)                     \
+    UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Id, _tag, \
+               UNION_MAKE(_spec::Id, commonTag, _field))
+
+#define MAKE_EXTENSION_PARAMETER_ID(_effect, _tag, _field)                  \
+    UNION_MAKE(aidl::android::hardware::audio::effect::Parameter::Id, _tag, \
+               UNION_MAKE(_effect::Id, vendorExtensionTag, _field))
+
+#define VENDOR_EXTENSION_GET_AND_RETURN(_effect, _tag, _param)                                    \
+    {                                                                                             \
+        aidl::android::hardware::audio::effect::VendorExtension _extId = VALUE_OR_RETURN_STATUS(  \
+                aidl::android::legacy2aidl_EffectParameterReader_Param_VendorExtension(_param));  \
+        aidl::android::hardware::audio::effect::Parameter::Id _id =                               \
+                MAKE_EXTENSION_PARAMETER_ID(_effect, _tag##Tag, _extId);                          \
+        aidl::android::hardware::audio::effect::Parameter _aidlParam;                             \
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(_id, &_aidlParam))); \
+        aidl::android::hardware::audio::effect::VendorExtension _ext =                            \
+                VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(                              \
+                        _aidlParam, _effect, _tag, _effect::vendor, VendorExtension));            \
+        return VALUE_OR_RETURN_STATUS(                                                            \
+                aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(_aidlParam,   \
+                                                                                    _param));     \
+    }
+
+ConversionResult<uint32_t> aidl2legacy_Flags_Type_uint32(
+        ::aidl::android::hardware::audio::effect::Flags::Type type);
+ConversionResult<uint32_t> aidl2legacy_Flags_Insert_uint32(
+        ::aidl::android::hardware::audio::effect::Flags::Insert insert);
+ConversionResult<uint32_t> aidl2legacy_Flags_Volume_uint32(
+        ::aidl::android::hardware::audio::effect::Flags::Volume volume);
+ConversionResult<uint32_t> aidl2legacy_Flags_HardwareAccelerator_uint32(
+        ::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator hwAcceleratorMode);
+ConversionResult<uint32_t> aidl2legacy_Flags_uint32(
+        const ::aidl::android::hardware::audio::effect::Flags aidl);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Type>
+legacy2aidl_uint32_Flags_Type(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Insert>
+legacy2aidl_uint32_Flags_Insert(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::Volume>
+legacy2aidl_uint32_Flags_Volume(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags::HardwareAccelerator>
+legacy2aidl_uint32_Flags_HardwareAccelerator(uint32_t legacy);
+ConversionResult<::aidl::android::hardware::audio::effect::Flags> legacy2aidl_uint32_Flags(
+        uint32_t hal);
+
+ConversionResult<effect_descriptor_t> aidl2legacy_Descriptor_effect_descriptor(
+        const ::aidl::android::hardware::audio::effect::Descriptor& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Descriptor>
+legacy2aidl_effect_descriptor_Descriptor(const effect_descriptor_t& hal);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_echoDelay(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_echoDelay_Parameter_aec(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_aec_uint32_mobileMode(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_mobileMode_Parameter_aec(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_levelEstimator(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_levelEstimator_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_agc_uint32_saturationMargin(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint32_saturationMargin_Parameter_agc(uint32_t legacy);
+
+ConversionResult<uint16_t> aidl2legacy_Parameter_BassBoost_uint16_strengthPm(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_uint16_strengthPm_Parameter_BassBoost(uint16_t legacy);
+
+ConversionResult<int16_t> aidl2legacy_Parameter_Downmix_int16_type(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_int16_type_Parameter_Downmix(int16_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference>
+legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(int32_t legacy);
+ConversionResult<int32_t> aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+        ::aidl::android::hardware::audio::effect::DynamicsProcessing::ResolutionPreference aidl);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(
+        ::aidl::android::hardware::audio::effect::Visualizer::ScalingMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::ScalingMode>
+legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(uint32_t legacy);
+
+ConversionResult<uint32_t> aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(
+        ::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode aidl);
+ConversionResult<::aidl::android::hardware::audio::effect::Visualizer::MeasurementMode>
+legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(uint32_t legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_EffectParameterReader_ParameterExtension(
+        ::android::effect::utils::EffectParamReader& param);
+ConversionResult<::android::status_t> aidl2legacy_ParameterExtension_EffectParameterWriter(
+        const ::aidl::android::hardware::audio::effect::Parameter& aidl,
+        ::android::effect::utils::EffectParamWriter& legacy);
+
+ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension>
+legacy2aidl_EffectParameterReader_Param_VendorExtension(
+        ::android::effect::utils::EffectParamReader& param);
+ConversionResult<::aidl::android::hardware::audio::effect::VendorExtension>
+legacy2aidl_EffectParameterReader_Data_VendorExtension(
+        ::android::effect::utils::EffectParamReader& param);
+
+ConversionResult<::android::status_t> aidl2legacy_VendorExtension_EffectParameterWriter_Data(
+        ::android::effect::utils::EffectParamWriter& param,
+        ::aidl::android::hardware::audio::effect::VendorExtension ext);
+ConversionResult<::aidl::android::hardware::audio::effect::Parameter>
+legacy2aidl_EffectParameterReader_ParameterExtension(
+        ::android::effect::utils::EffectParamReader& param);
+
+}  // namespace android
+}  // namespace aidl
diff --git a/media/audioaidlconversion/include/media/AidlConversionNdk.h b/media/audioaidlconversion/include/media/AidlConversionNdk.h
new file mode 100644
index 0000000..e92f1a9
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionNdk.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+/**
+ * Can only handle conversion between AIDL (NDK backend) and legacy types.
+ */
+
+#include <string>
+#include <vector>
+
+#include <hardware/audio_effect.h>
+#include <system/audio_effect.h>
+
+#include <aidl/android/hardware/audio/common/PlaybackTrackMetadata.h>
+#include <aidl/android/hardware/audio/common/RecordTrackMetadata.h>
+#include <aidl/android/media/audio/common/AudioConfig.h>
+#include <media/AidlConversionUtil.h>
+
+namespace aidl {
+namespace android {
+
+ConversionResult<buffer_config_t> aidl2legacy_AudioConfigBase_buffer_config_t(
+        const media::audio::common::AudioConfigBase& aidl, bool isInput);
+ConversionResult<media::audio::common::AudioConfigBase> legacy2aidl_buffer_config_t_AudioConfigBase(
+        const buffer_config_t& legacy, bool isInput);
+
+::android::status_t aidl2legacy_AudioAttributesTags(
+        const std::vector<std::string>& aidl, char* legacy);
+ConversionResult<std::vector<std::string>> legacy2aidl_AudioAttributesTags(const char* legacy);
+
+ConversionResult<playback_track_metadata_v7>
+aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(
+        const hardware::audio::common::PlaybackTrackMetadata& aidl);
+ConversionResult<hardware::audio::common::PlaybackTrackMetadata>
+legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(
+        const playback_track_metadata_v7& legacy);
+
+ConversionResult<record_track_metadata_v7>
+aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(
+        const hardware::audio::common::RecordTrackMetadata& aidl);
+ConversionResult<hardware::audio::common::RecordTrackMetadata>
+legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(const record_track_metadata_v7& legacy);
+
+}  // namespace android
+}  // namespace aidl
diff --git a/media/libaudioclient/include/media/AidlConversionUtil.h b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
similarity index 70%
rename from media/libaudioclient/include/media/AidlConversionUtil.h
rename to media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
index 8817c35..ed91e2c 100644
--- a/media/libaudioclient/include/media/AidlConversionUtil.h
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil-impl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,20 +14,41 @@
  * limitations under the License.
  */
 
-#pragma once
+// WARNING: This file is intended for multiple inclusion, one time
+// with BACKEND_NDK_IMPL defined, one time without it.
+// Do not include directly, use 'AidlConversionUtil.h'.
+#if (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_NDK)) || \
+    (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP))
+#if defined(BACKEND_NDK_IMPL)
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_NDK
+#else
+#define AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP
+#endif  // BACKEND_NDK_IMPL
 
 #include <limits>
 #include <type_traits>
 #include <utility>
 
-#include <binder/Enums.h>
+#include <android-base/expected.h>
 #include <binder/Status.h>
-#include <error/Result.h>
 
+#if defined(BACKEND_NDK_IMPL)
+#include <android/binder_auto_utils.h>
+#include <android/binder_enums.h>
+#include <android/binder_status.h>
+
+namespace aidl {
+#else
+#include <binder/Enums.h>
+#endif  // BACKEND_NDK_IMPL
 namespace android {
 
+#if defined(BACKEND_NDK_IMPL)
+// This adds `::aidl::android::ConversionResult` for convenience.
+// Otherwise, it would be required to write `::android::ConversionResult` everywhere.
 template <typename T>
-using ConversionResult = error::Result<T>;
+using ConversionResult = ::android::ConversionResult<T>;
+#endif  // BACKEND_NDK_IMPL
 
 /**
  * A generic template to safely cast between integral types, respecting limits of the destination
@@ -39,15 +60,15 @@
     // have the signed converted to unsigned and produce wrong results.
     if (std::is_signed_v<From> && !std::is_signed_v<To>) {
         if (from < 0 || from > std::numeric_limits<To>::max()) {
-            return base::unexpected(BAD_VALUE);
+            return ::android::base::unexpected(::android::BAD_VALUE);
         }
     } else if (std::is_signed_v<To> && !std::is_signed_v<From>) {
         if (from > std::numeric_limits<To>::max()) {
-            return base::unexpected(BAD_VALUE);
+            return ::android::base::unexpected(::android::BAD_VALUE);
         }
     } else {
         if (from < std::numeric_limits<To>::min() || from > std::numeric_limits<To>::max()) {
-            return base::unexpected(BAD_VALUE);
+            return ::android::base::unexpected(::android::BAD_VALUE);
         }
     }
     return static_cast<To>(from);
@@ -67,14 +88,14 @@
  * A generic template that helps convert containers of convertible types, using iterators.
  */
 template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRange(InputIterator start,
+::android::status_t convertRange(InputIterator start,
                       InputIterator end,
                       OutputIterator out,
                       const Func& itemConversion) {
     for (InputIterator iter = start; iter != end; ++iter, ++out) {
         *out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
     }
-    return OK;
+    return ::android::OK;
 }
 
 /**
@@ -82,7 +103,7 @@
  * Uses a limit as maximum conversion items.
  */
 template<typename InputIterator, typename OutputIterator, typename Func>
-status_t convertRangeWithLimit(InputIterator start,
+::android::status_t convertRangeWithLimit(InputIterator start,
                       InputIterator end,
                       OutputIterator out,
                       const Func& itemConversion,
@@ -94,7 +115,7 @@
     for (InputIterator iter = start; (iter != last); ++iter, ++out) {
         *out = VALUE_OR_RETURN_STATUS(itemConversion(*iter));
     }
-    return OK;
+    return ::android::OK;
 }
 
 /**
@@ -140,7 +161,7 @@
     OutputContainer output;
     auto ins = std::inserter(output, output.begin());
     for (const auto& item1 : input1) {
-        RETURN_IF_ERROR(iter2 != input2.end() ? OK : BAD_VALUE);
+        RETURN_IF_ERROR(iter2 != input2.end() ? ::android::OK : ::android::BAD_VALUE);
         *ins = VALUE_OR_RETURN(itemConversion(item1, *iter2++));
     }
     return output;
@@ -248,7 +269,8 @@
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Utilities for working with AIDL unions.
 // UNION_GET(obj, fieldname) returns a ConversionResult<T> containing either the strongly-typed
-//   value of the respective field, or BAD_VALUE if the union is not set to the requested field.
+//   value of the respective field, or ::android::BAD_VALUE if the union is not set to the requested
+//   field.
 // UNION_SET(obj, fieldname, value) sets the requested field to the given value.
 
 template<typename T, typename T::Tag tag>
@@ -257,7 +279,7 @@
 template<typename T, typename T::Tag tag>
 ConversionResult<UnionFieldType<T, tag>> unionGetField(const T& u) {
     if (u.getTag() != tag) {
-        return base::unexpected(BAD_VALUE);
+        return ::android::base::unexpected(::android::BAD_VALUE);
     }
     return u.template get<tag>();
 }
@@ -268,6 +290,8 @@
 #define UNION_SET(u, field, value) \
     (u).set<std::decay_t<decltype(u)>::Tag::field>(value)
 
+#define UNION_MAKE(u, field, value) u::make<u::Tag::field>(value)
+
 namespace aidl_utils {
 
 /**
@@ -275,7 +299,11 @@
  */
 template <typename T>
 bool isValidEnum(T value) {
-    constexpr android::enum_range<T> er{};
+#if defined(BACKEND_NDK_IMPL)
+    constexpr ndk::enum_range<T> er{};
+#else
+    constexpr ::android::enum_range<T> er{};
+#endif
     return std::find(er.begin(), er.end(), value) != er.end();
 }
 
@@ -294,7 +322,7 @@
 }
 
 /**
- * Return the equivalent Android status_t from a binder exception code.
+ * Return the equivalent Android ::android::status_t from a binder exception code.
  *
  * Generally one should use statusTFromBinderStatus() instead.
  *
@@ -304,33 +332,33 @@
  * Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
  * can be found from transactionError() or serviceSpecificErrorCode().
  */
-static inline status_t statusTFromExceptionCode(int32_t exceptionCode) {
+static inline ::android::status_t statusTFromExceptionCode(int32_t exceptionCode) {
     using namespace ::android::binder;
     switch (exceptionCode) {
         case Status::EX_NONE:
-            return OK;
-        case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
-            return PERMISSION_DENIED;
-        case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
-        case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
-        case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
-            return BAD_VALUE;
-        case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
-        case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
-            return INVALID_OPERATION;
+            return ::android::OK;
+        case Status::EX_SECURITY:  // Java SecurityException, rethrows locally in Java
+            return ::android::PERMISSION_DENIED;
+        case Status::EX_BAD_PARCELABLE:  // Java BadParcelableException, rethrows in Java
+        case Status::EX_ILLEGAL_ARGUMENT:  // Java IllegalArgumentException, rethrows in Java
+        case Status::EX_NULL_POINTER:  // Java NullPointerException, rethrows in Java
+            return ::android::BAD_VALUE;
+        case Status::EX_ILLEGAL_STATE:  // Java IllegalStateException, rethrows in Java
+        case Status::EX_UNSUPPORTED_OPERATION:  // Java UnsupportedOperationException, rethrows
+            return ::android::INVALID_OPERATION;
         case Status::EX_HAS_REPLY_HEADER: // Native strictmode violation
-        case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
-        case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
+        case Status::EX_PARCELABLE:  // Java bootclass loader (not standard exception), rethrows
+        case Status::EX_NETWORK_MAIN_THREAD:  // Java NetworkOnMainThreadException, rethrows
         case Status::EX_TRANSACTION_FAILED: // Native - see error code
-        case Status::EX_SERVICE_SPECIFIC:  // Java ServiceSpecificException,
-                                           // rethrows in Java with integer error code
-            return UNKNOWN_ERROR;
+        case Status::EX_SERVICE_SPECIFIC:   // Java ServiceSpecificException,
+                                            // rethrows in Java with integer error code
+            return ::android::UNKNOWN_ERROR;
     }
-    return UNKNOWN_ERROR;
+    return ::android::UNKNOWN_ERROR;
 }
 
 /**
- * Return the equivalent Android status_t from a binder status.
+ * Return the equivalent Android ::android::status_t from a binder status.
  *
  * Used to handle errors from a AIDL method declaration
  *
@@ -340,8 +368,8 @@
  *
  * return_type method(type0 param0, ...)
  */
-static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
-    return status.isOk() ? OK // check OK,
+static inline ::android::status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+    return status.isOk() ? ::android::OK // check ::android::OK,
         : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
                                             // (fromServiceSpecificError)
         ?: status.transactionError() // a native binder transaction error (fromStatusT)
@@ -349,6 +377,20 @@
                                                     // standard Java exception (fromExceptionCode)
 }
 
+#if defined(BACKEND_NDK_IMPL)
+static inline ::android::status_t statusTFromBinderStatus(const ::ndk::ScopedAStatus &status) {
+    // What we want to do is to 'return statusTFromBinderStatus(status.get()->get())'
+    // However, since the definition of AStatus is not exposed, we have to do the same
+    // via methods of ScopedAStatus:
+    return status.isOk() ? ::android::OK // check ::android::OK,
+        : status.getServiceSpecificError() // service-side error, not standard Java exception
+                                           // (fromServiceSpecificError)
+        ?: status.getStatus() // a native binder transaction error (fromStatusT)
+        ?: statusTFromExceptionCode(status.getExceptionCode()); // a service-side error with a
+                                                     // standard Java exception (fromExceptionCode)
+}
+#endif
+
 /**
  * Return a binder::Status from native service status.
  *
@@ -356,23 +398,23 @@
  * where Java callers expect an exception, not an integer return value.
  */
 static inline ::android::binder::Status binderStatusFromStatusT(
-        status_t status, const char *optionalMessage = nullptr) {
+        ::android::status_t status, const char *optionalMessage = nullptr) {
     const char * const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
     // From binder::Status instructions:
     //  Prefer a generic exception code when possible, then a service specific
-    //  code, and finally a status_t for low level failures or legacy support.
+    //  code, and finally a ::android::status_t for low level failures or legacy support.
     //  Exception codes and service specific errors map to nicer exceptions for
     //  Java clients.
 
     using namespace ::android::binder;
     switch (status) {
-        case OK:
+        case ::android::OK:
             return Status::ok();
-        case PERMISSION_DENIED: // throw SecurityException on Java side
+        case ::android::PERMISSION_DENIED: // throw SecurityException on Java side
             return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
-        case BAD_VALUE: // throw IllegalArgumentException on Java side
+        case ::android::BAD_VALUE: // throw IllegalArgumentException on Java side
             return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
-        case INVALID_OPERATION: // throw IllegalStateException on Java side
+        case ::android::INVALID_OPERATION: // throw IllegalStateException on Java side
             return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
     }
 
@@ -383,7 +425,14 @@
     return Status::fromServiceSpecificError(status, emptyIfNull);
 }
 
-
 } // namespace aidl_utils
 
 }  // namespace android
+
+#if defined(BACKEND_NDK_IMPL)
+}  // namespace aidl
+#endif
+
+// (defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_NDK)) || \
+// (!defined(BACKEND_NDK_IMPL) && !defined(AUDIO_AIDL_CONVERSION_AIDL_CONVERSION_UTIL_CPP))
+#endif
diff --git a/media/audioaidlconversion/include/media/AidlConversionUtil.h b/media/audioaidlconversion/include/media/AidlConversionUtil.h
new file mode 100644
index 0000000..b846436
--- /dev/null
+++ b/media/audioaidlconversion/include/media/AidlConversionUtil.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <error/Result.h>
+
+namespace android {
+// `ConversionResult` is always defined in the `::android` namespace,
+// so that it can be found from any nested namespace.
+// See below for the convenience alias specific to the NDK backend.
+template <typename T>
+using ConversionResult = ::android::error::Result<T>;
+}  // namespace android
+
+// Include 'AidlConversionUtil.h' once if 'BACKEND_NDK' is defined,
+// or no 'BACKEND_*' is defined (C++ backend). Include twice if
+// 'BACKEND_CPP_NDK' is defined: once with 'BACKEND_NDK_IMPL', once w/o defines.
+
+#if defined(BACKEND_CPP_NDK) || defined(BACKEND_NDK)
+#define BACKEND_NDK_IMPL
+#include <media/AidlConversionUtil-impl.h>
+#undef BACKEND_NDK_IMPL
+#endif
+
+#if defined(BACKEND_CPP_NDK) || !defined(BACKEND_NDK)
+#include <media/AidlConversionUtil-impl.h>
+#endif
diff --git a/media/audioaidlconversion/tests/Android.bp b/media/audioaidlconversion/tests/Android.bp
new file mode 100644
index 0000000..de7c8a2
--- /dev/null
+++ b/media/audioaidlconversion/tests/Android.bp
@@ -0,0 +1,46 @@
+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"],
+}
+
+cc_defaults {
+    name: "libaudio_aidl_conversion_tests_defaults",
+    test_suites: ["device-tests"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+    },
+}
+
+cc_test {
+    name: "audio_aidl_ndk_conversion_tests",
+
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_static",
+        "latest_android_hardware_audio_common_ndk_static",
+        "libaudio_aidl_conversion_tests_defaults",
+    ],
+    srcs: ["audio_aidl_ndk_conversion_tests.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "libaudio_aidl_conversion_common_ndk",
+    ],
+    cflags: [
+        "-DBACKEND_NDK",
+    ],
+}
diff --git a/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
new file mode 100644
index 0000000..c505e60
--- /dev/null
+++ b/media/audioaidlconversion/tests/audio_aidl_ndk_conversion_tests.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <iostream>
+#include <type_traits>
+
+#include <gtest/gtest.h>
+
+#include <media/AidlConversionNdk.h>
+
+namespace {
+template<typename> struct mf_traits {};
+template<class T, class U> struct mf_traits<U T::*> {
+    using member_type = U;
+};
+}  // namespace
+
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace aidl::android::hardware::audio::common {
+    template <typename P>
+    std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
+            std::ostream&> operator<<(std::ostream& os, const P& p) {
+        return os << p.toString();
+    }
+    template <typename E>
+    std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
+        return os << toString(e);
+    }
+}  // namespace aidl::android::hardware::audio::common
+
+using aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioUsage;
+using namespace aidl::android;   // for conversion functions
+
+TEST(AudioPlaybackTrackMetadata, Aidl2Legacy2Aidl) {
+    const PlaybackTrackMetadata initial{ .usage = AudioUsage::UNKNOWN };
+    auto conv = aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioPlaybackTrackMetadata, NonVendorTags) {
+    PlaybackTrackMetadata initial{ .usage = AudioUsage::UNKNOWN };
+    initial.tags.emplace_back("random string");  // Must be filtered out.
+    initial.tags.emplace_back("VX_GOOGLE_42");
+    auto conv = aidl2legacy_PlaybackTrackMetadata_playback_track_metadata_v7(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    ASSERT_EQ(1, convBack.value().tags.size());
+    EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
+}
+
+TEST(AudioRecordTrackMetadata, Aidl2Legacy2Aidl) {
+    const RecordTrackMetadata initial{ .source = AudioSource::DEFAULT };
+    auto conv = aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioRecordTrackMetadata, NonVendorTags) {
+    RecordTrackMetadata initial{ .source = AudioSource::DEFAULT };
+    initial.tags.emplace_back("random string");  // Must be filtered out.
+    initial.tags.emplace_back("VX_GOOGLE_42");
+    auto conv = aidl2legacy_RecordTrackMetadata_record_track_metadata_v7(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_record_track_metadata_v7_RecordTrackMetadata(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    ASSERT_EQ(1, convBack.value().tags.size());
+    EXPECT_EQ(initial.tags[1], convBack.value().tags[0]);
+}
diff --git a/media/audioserver/audioserver.rc b/media/audioserver/audioserver.rc
index c4a6601..d62dd91 100644
--- a/media/audioserver/audioserver.rc
+++ b/media/audioserver/audioserver.rc
@@ -7,11 +7,10 @@
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
     onrestart restart vendor.audio-hal
+    onrestart restart vendor.audio-hal-aidl
+    onrestart restart vendor.audio-effect-hal-aidl
     onrestart restart vendor.audio-hal-4-0-msd
     onrestart restart audio_proxy_service
-    # Keep the original service names for backward compatibility
-    onrestart restart vendor.audio-hal-2-0
-    onrestart restart audio-hal-2-0
 
 on property:vts.native_server.on=1
     stop audioserver
@@ -20,42 +19,39 @@
 
 on property:init.svc.audioserver=stopped
     stop vendor.audio-hal
+    stop vendor.audio-hal-aidl
+    stop vendor.audio-effect-hal-aidl
     stop vendor.audio-hal-4-0-msd
     stop audio_proxy_service
-    # Keep the original service names for backward compatibility
-    stop vendor.audio-hal-2-0
-    stop audio-hal-2-0
     # See b/155364397. Need to have HAL service running for VTS.
     # Can't use 'restart' because then HAL service would restart
     # audioserver bringing it back into running state.
     start vendor.audio-hal
+    start vendor.audio-hal-aidl
+    start vendor.audio-effect-hal-aidl
     start vendor.audio-hal-4-0-msd
     start audio_proxy_service
-    # Keep the original service names for backward compatibility
-    start vendor.audio-hal-2-0
-    start audio-hal-2-0
 
 on property:init.svc.audioserver=running
     start vendor.audio-hal
+    start vendor.audio-hal-aidl
+    start vendor.audio-effect-hal-aidl
     start vendor.audio-hal-4-0-msd
     start audio_proxy_service
-    # Keep the original service names for backward compatibility
-    start vendor.audio-hal-2-0
-    start audio-hal-2-0
 
 on property:sys.audio.restart.hal=1
     # See b/159966243. Avoid restart loop between audioserver and HAL.
     # Keep the original service names for backward compatibility
     stop vendor.audio-hal
+    stop vendor.audio-hal-aidl
+    stop vendor.audio-effect-hal-aidl
     stop vendor.audio-hal-4-0-msd
     stop audio_proxy_service
-    stop vendor.audio-hal-2-0
-    stop audio-hal-2-0
     start vendor.audio-hal
+    start vendor.audio-hal-aidl
+    start vendor.audio-effect-hal-aidl
     start vendor.audio-hal-4-0-msd
     start audio_proxy_service
-    start vendor.audio-hal-2-0
-    start audio-hal-2-0
     # reset the property
     setprop sys.audio.restart.hal 0
 
diff --git a/media/codec2/TEST_MAPPING b/media/codec2/TEST_MAPPING
index 90bb054..8a894f3 100644
--- a/media/codec2/TEST_MAPPING
+++ b/media/codec2/TEST_MAPPING
@@ -8,17 +8,6 @@
   ],
   "presubmit-large": [
     {
-      "name": "CtsMediaMiscTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
-        }
-      ]
-    },
-    {
       "name": "CtsMediaAudioTestCases",
       "options": [
         {
@@ -35,50 +24,6 @@
           "exclude-filter": "android.media.audio.cts.AudioRecordTest"
         }
       ]
-    },
-    {
-      "name": "CtsMediaDecoderTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
-        }
-      ]
-    },
-    {
-      "name": "CtsMediaEncoderTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
-        }
-      ]
-    },
-    {
-      "name": "CtsMediaCodecTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
-        }
-      ]
-    },
-    {
-      "name": "CtsMediaPlayerTestCases",
-      "options": [
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "android.platform.test.annotations.RequiresDevice"
-        }
-      ]
     }
   ]
 }
diff --git a/media/codec2/components/aac/C2SoftAacDec.cpp b/media/codec2/components/aac/C2SoftAacDec.cpp
index 4e4a9a1..d1b08bd 100644
--- a/media/codec2/components/aac/C2SoftAacDec.cpp
+++ b/media/codec2/components/aac/C2SoftAacDec.cpp
@@ -275,7 +275,8 @@
       mStreamInfo(nullptr),
       mSignalledError(false),
       mOutputPortDelay(kDefaultOutputPortDelay),
-      mOutputDelayRingBuffer(nullptr) {
+      mOutputDelayRingBuffer(nullptr),
+      mDeviceApiLevel(android_get_device_api_level()) {
 }
 
 C2SoftAacDec::~C2SoftAacDec() {
@@ -891,7 +892,7 @@
             work->worklets.front()->output.configUpdate.push_back(
                     C2Param::Copy(currentBoostFactor));
 
-            if (android_get_device_api_level() < __ANDROID_API_S__) {
+            if (mDeviceApiLevel < __ANDROID_API_S__) {
                 // We used to report DRC compression mode in the output format
                 // in Q and R, but stopped doing that in S
                 C2StreamDrcCompressionModeTuning::input currentCompressMode(0u,
diff --git a/media/codec2/components/aac/C2SoftAacDec.h b/media/codec2/components/aac/C2SoftAacDec.h
index b45f148..f85d45f 100644
--- a/media/codec2/components/aac/C2SoftAacDec.h
+++ b/media/codec2/components/aac/C2SoftAacDec.h
@@ -97,6 +97,7 @@
     int32_t mOutputDelayRingBufferWritePos;
     int32_t mOutputDelayRingBufferReadPos;
     int32_t mOutputDelayRingBufferFilled;
+    int mDeviceApiLevel;
     bool outputDelayRingBufferPutSamples(INT_PCM *samples, int numSamples);
     int32_t outputDelayRingBufferGetSamples(INT_PCM *samples, int numSamples);
     int32_t outputDelayRingBufferSamplesAvailable();
diff --git a/media/codec2/components/avc/C2SoftAvcDec.cpp b/media/codec2/components/avc/C2SoftAvcDec.cpp
index 953afc5..96a4c4a 100644
--- a/media/codec2/components/avc/C2SoftAvcDec.cpp
+++ b/media/codec2/components/avc/C2SoftAvcDec.cpp
@@ -671,6 +671,9 @@
 void C2SoftAvcDec::resetPlugin() {
     mSignalledOutputEos = false;
     mTimeStart = mTimeEnd = systemTime();
+    if (mOutBlock) {
+        mOutBlock.reset();
+    }
 }
 
 status_t C2SoftAvcDec::deleteDecoder() {
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.cpp b/media/codec2/components/avc/C2SoftAvcEnc.cpp
index 8b46d3f..5d2856a 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.cpp
+++ b/media/codec2/components/avc/C2SoftAvcEnc.cpp
@@ -392,9 +392,9 @@
     static C2R PictureQuantizationSetter(bool mayBlock,
                                          C2P<C2StreamPictureQuantizationTuning::output> &me) {
         (void)mayBlock;
-        (void)me;
 
-        // TODO: refactor with same algorithm in the SetQp()
+        // these are the ones we're going to set, so want them to default
+        // to the DEFAULT values for the codec
         int32_t iMin = DEFAULT_I_QP_MIN, pMin = DEFAULT_P_QP_MIN, bMin = DEFAULT_B_QP_MIN;
         int32_t iMax = DEFAULT_I_QP_MAX, pMax = DEFAULT_P_QP_MAX, bMax = DEFAULT_B_QP_MAX;
 
@@ -419,13 +419,14 @@
         ALOGV("PictureQuantizationSetter(entry): i %d-%d p %d-%d b %d-%d",
               iMin, iMax, pMin, pMax, bMin, bMax);
 
-        // ensure we have legal values
-        iMax = std::clamp(iMax, CODEC_QP_MIN, CODEC_QP_MAX);
-        iMin = std::clamp(iMin, CODEC_QP_MIN, CODEC_QP_MAX);
-        pMax = std::clamp(pMax, CODEC_QP_MIN, CODEC_QP_MAX);
-        pMin = std::clamp(pMin, CODEC_QP_MIN, CODEC_QP_MAX);
-        bMax = std::clamp(bMax, CODEC_QP_MIN, CODEC_QP_MAX);
-        bMin = std::clamp(bMin, CODEC_QP_MIN, CODEC_QP_MAX);
+        // min is clamped to [AVC_QP_MIN, max] to avoid error
+        // cases where layer.min > layer.max
+        iMax = std::clamp(iMax, AVC_QP_MIN, AVC_QP_MAX);
+        iMin = std::clamp(iMin, AVC_QP_MIN, iMax);
+        pMax = std::clamp(pMax, AVC_QP_MIN, AVC_QP_MAX);
+        pMin = std::clamp(pMin, AVC_QP_MIN, pMax);
+        bMax = std::clamp(bMax, AVC_QP_MIN, AVC_QP_MAX);
+        bMin = std::clamp(bMin, AVC_QP_MIN, bMax);
 
         // put them back into the structure
         for (size_t i = 0; i < me.v.flexCount(); ++i) {
@@ -819,7 +820,8 @@
     s_qp_ip.e_cmd = IVE_CMD_VIDEO_CTL;
     s_qp_ip.e_sub_cmd = IVE_CMD_CTL_SET_QP;
 
-    // TODO: refactor with same algorithm in the PictureQuantizationSetter()
+    // we resolved out-of-bound and unspecified values in PictureQuantizationSetter()
+    // so we can start with defaults that are overridden as needed.
     int32_t iMin = DEFAULT_I_QP_MIN, pMin = DEFAULT_P_QP_MIN, bMin = DEFAULT_B_QP_MIN;
     int32_t iMax = DEFAULT_I_QP_MAX, pMax = DEFAULT_P_QP_MAX, bMax = DEFAULT_B_QP_MAX;
 
@@ -1766,17 +1768,20 @@
     //         }
     //     }
     // }
-    std::shared_ptr<const C2GraphicView> view;
+    std::shared_ptr<C2GraphicView> view;
     std::shared_ptr<C2Buffer> inputBuffer;
     if (!work->input.buffers.empty()) {
         inputBuffer = work->input.buffers[0];
-        view = std::make_shared<const C2GraphicView>(
+        view = std::make_shared<C2GraphicView>(
                 inputBuffer->data().graphicBlocks().front().map().get());
         if (view->error() != C2_OK) {
             ALOGE("graphic view map err = %d", view->error());
             work->workletsProcessed = 1u;
             return;
         }
+        //(b/232396154)
+        //workaround for incorrect crop size in view when using surface mode
+        view->setCrop_be(C2Rect(mSize->width, mSize->height));
     }
 
     do {
diff --git a/media/codec2/components/avc/C2SoftAvcEnc.h b/media/codec2/components/avc/C2SoftAvcEnc.h
index 293867d..cde6604 100644
--- a/media/codec2/components/avc/C2SoftAvcEnc.h
+++ b/media/codec2/components/avc/C2SoftAvcEnc.h
@@ -103,8 +103,8 @@
 /** limits as specified by h264
  *  (QP_MIN==4 is actually a limitation of this SW codec, not the H.264 standard)
  **/
-#define CODEC_QP_MIN                4
-#define CODEC_QP_MAX                51
+#define AVC_QP_MIN                4
+#define AVC_QP_MAX                51
 
 
 #define MIN(a, b) ((a) < (b))? (a) : (b)
diff --git a/media/codec2/components/base/SimpleC2Component.cpp b/media/codec2/components/base/SimpleC2Component.cpp
index 9d4f049..199875d 100644
--- a/media/codec2/components/base/SimpleC2Component.cpp
+++ b/media/codec2/components/base/SimpleC2Component.cpp
@@ -190,7 +190,7 @@
 // matrix conversion coefficients
 // (see media/libstagefright/colorconverter/ColorConverter.cpp for more details)
 struct Coeffs {
-    int32_t _y, _b_u, _g_u, _g_v, _r_v, _c16;
+    int32_t _y, _r_v, _g_u, _g_v, _b_u, _c16;
 };
 
 static const struct Coeffs GetCoeffsForAspects(const C2ColorAspectsStruct &aspects) {
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 4dec57f..d234f21 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -102,6 +102,29 @@
             .withSetter(Hdr10PlusInfoOutputSetter)
             .build());
 
+    // default static info
+    C2HdrStaticMetadataStruct defaultStaticInfo{};
+    helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
+    addParameter(
+        DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
+            .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
+            .withFields({
+                C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
+                C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
+                C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
+                C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
+                C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)
+            })
+            .withSetter(HdrStaticInfoSetter)
+            .build());
+
     addParameter(
         DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
             .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
@@ -331,6 +354,47 @@
   // unsafe getters
   std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const { return mPixelFormat; }
 
+  static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output> &me) {
+    (void)mayBlock;
+    if (me.v.mastering.red.x > 1) {
+      me.set().mastering.red.x = 1;
+    }
+    if (me.v.mastering.red.y > 1) {
+      me.set().mastering.red.y = 1;
+    }
+    if (me.v.mastering.green.x > 1) {
+      me.set().mastering.green.x = 1;
+    }
+    if (me.v.mastering.green.y > 1) {
+      me.set().mastering.green.y = 1;
+    }
+    if (me.v.mastering.blue.x > 1) {
+      me.set().mastering.blue.x = 1;
+    }
+    if (me.v.mastering.blue.y > 1) {
+      me.set().mastering.blue.y = 1;
+    }
+    if (me.v.mastering.white.x > 1) {
+      me.set().mastering.white.x = 1;
+    }
+    if (me.v.mastering.white.y > 1) {
+      me.set().mastering.white.y = 1;
+    }
+    if (me.v.mastering.maxLuminance > 65535.0) {
+      me.set().mastering.maxLuminance = 65535.0;
+    }
+    if (me.v.mastering.minLuminance > 6.5535) {
+      me.set().mastering.minLuminance = 6.5535;
+    }
+    if (me.v.maxCll > 65535.0) {
+      me.set().maxCll = 65535.0;
+    }
+    if (me.v.maxFall > 65535.0) {
+      me.set().maxFall = 65535.0;
+    }
+    return C2R::Ok();
+  }
+
  private:
   std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
   std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
@@ -343,6 +407,7 @@
   std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
   std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
   std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
+  std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
 };
 
 C2SoftGav1Dec::C2SoftGav1Dec(const char *name, c2_node_id_t id,
@@ -558,6 +623,76 @@
   }
 }
 
+void C2SoftGav1Dec::getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
+                                       const std::unique_ptr<C2Work> &work) {
+  C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
+  bool infoPresent = false;
+  if (buffer->has_hdr_mdcv) {
+    // hdr_mdcv.primary_chromaticity_* values are in 0.16 fixed-point format.
+    hdrStaticMetadataInfo.mastering.red.x = buffer->hdr_mdcv.primary_chromaticity_x[0] / 65536.0;
+    hdrStaticMetadataInfo.mastering.red.y = buffer->hdr_mdcv.primary_chromaticity_y[0] / 65536.0;
+
+    hdrStaticMetadataInfo.mastering.green.x = buffer->hdr_mdcv.primary_chromaticity_x[1] / 65536.0;
+    hdrStaticMetadataInfo.mastering.green.y = buffer->hdr_mdcv.primary_chromaticity_y[1] / 65536.0;
+
+    hdrStaticMetadataInfo.mastering.blue.x = buffer->hdr_mdcv.primary_chromaticity_x[2] / 65536.0;
+    hdrStaticMetadataInfo.mastering.blue.y = buffer->hdr_mdcv.primary_chromaticity_y[2] / 65536.0;
+
+    // hdr_mdcv.white_point_chromaticity_* values are in 0.16 fixed-point format.
+    hdrStaticMetadataInfo.mastering.white.x = buffer->hdr_mdcv.white_point_chromaticity_x / 65536.0;
+    hdrStaticMetadataInfo.mastering.white.y = buffer->hdr_mdcv.white_point_chromaticity_y / 65536.0;
+
+    // hdr_mdcv.luminance_max is in 24.8 fixed-point format.
+    hdrStaticMetadataInfo.mastering.maxLuminance = buffer->hdr_mdcv.luminance_max / 256.0;
+    // hdr_mdcv.luminance_min is in 18.14 format.
+    hdrStaticMetadataInfo.mastering.minLuminance = buffer->hdr_mdcv.luminance_min / 16384.0;
+    infoPresent = true;
+  }
+
+  if (buffer->has_hdr_cll) {
+    hdrStaticMetadataInfo.maxCll = buffer->hdr_cll.max_cll;
+    hdrStaticMetadataInfo.maxFall = buffer->hdr_cll.max_fall;
+    infoPresent = true;
+  }
+  // config if static info has changed
+  if (infoPresent && !(hdrStaticMetadataInfo == mHdrStaticMetadataInfo)) {
+    mHdrStaticMetadataInfo = hdrStaticMetadataInfo;
+    work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(mHdrStaticMetadataInfo));
+  }
+}
+
+void C2SoftGav1Dec::getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
+                                         const std::unique_ptr<C2Work> &work) {
+  if (buffer->has_itut_t35) {
+    std::vector<uint8_t> payload;
+    size_t payloadSize = buffer->itut_t35.payload_size;
+    if (payloadSize > 0) {
+      payload.push_back(buffer->itut_t35.country_code);
+      if (buffer->itut_t35.country_code == 0xFF) {
+        payload.push_back(buffer->itut_t35.country_code_extension_byte);
+      }
+      payload.insert(payload.end(), buffer->itut_t35.payload_bytes,
+                     buffer->itut_t35.payload_bytes + buffer->itut_t35.payload_size);
+    }
+
+    std::unique_ptr<C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
+            C2StreamHdr10PlusInfo::output::AllocUnique(payload.size());
+    if (!hdr10PlusInfo) {
+      ALOGE("Hdr10PlusInfo allocation failed");
+      mSignalledError = true;
+      work->result = C2_NO_MEMORY;
+      return;
+    }
+    memcpy(hdr10PlusInfo->m.value, payload.data(), payload.size());
+
+    // config if hdr10Plus info has changed
+    if (nullptr == mHdr10PlusInfo || !(*hdr10PlusInfo == *mHdr10PlusInfo)) {
+      mHdr10PlusInfo = std::move(hdr10PlusInfo);
+      work->worklets.front()->output.configUpdate.push_back(std::move(mHdr10PlusInfo));
+    }
+  }
+}
+
 void C2SoftGav1Dec::getVuiParams(const libgav1::DecoderBuffer *buffer) {
     VuiColorAspects vuiColorAspects;
     vuiColorAspects.primaries = buffer->color_primary;
@@ -633,6 +768,9 @@
   }
 
   getVuiParams(buffer);
+  getHDRStaticParams(buffer, work);
+  getHDR10PlusInfoData(buffer, work);
+
   if (!(buffer->image_format == libgav1::kImageFormatYuv420 ||
         buffer->image_format == libgav1::kImageFormatMonochrome400)) {
     ALOGE("image_format %d not supported", buffer->image_format);
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index 3d4db55..f0e14d7 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -23,8 +23,8 @@
 
 #include <SimpleC2Component.h>
 #include <C2Config.h>
-#include "libgav1/src/gav1/decoder.h"
-#include "libgav1/src/gav1/decoder_settings.h"
+#include <gav1/decoder.h>
+#include <gav1/decoder_settings.h>
 
 namespace android {
 
@@ -61,6 +61,9 @@
   bool mSignalledOutputEos;
   bool mSignalledError;
 
+  C2StreamHdrStaticMetadataInfo::output mHdrStaticMetadataInfo;
+  std::unique_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfo = nullptr;
+
   // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid
   // converting them to C2 values for each frame
   struct VuiColorAspects {
@@ -86,6 +89,10 @@
   nsecs_t mTimeEnd = 0;    // Time at the end of decode()
 
   bool initDecoder();
+  void getHDRStaticParams(const libgav1::DecoderBuffer *buffer,
+                  const std::unique_ptr<C2Work> &work);
+  void getHDR10PlusInfoData(const libgav1::DecoderBuffer *buffer,
+                  const std::unique_ptr<C2Work> &work);
   void getVuiParams(const libgav1::DecoderBuffer *buffer);
   void destroyDecoder();
   void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
diff --git a/media/codec2/components/hevc/C2SoftHevcDec.cpp b/media/codec2/components/hevc/C2SoftHevcDec.cpp
index 5a660c5..15d6dcd 100644
--- a/media/codec2/components/hevc/C2SoftHevcDec.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcDec.cpp
@@ -664,6 +664,9 @@
 void C2SoftHevcDec::resetPlugin() {
     mSignalledOutputEos = false;
     mTimeStart = mTimeEnd = systemTime();
+    if (mOutBlock) {
+        mOutBlock.reset();
+    }
 }
 
 status_t C2SoftHevcDec::deleteDecoder() {
@@ -917,7 +920,8 @@
         if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
             if (mHeaderDecoded == false) {
                 mHeaderDecoded = true;
-                setParams(ALIGN128(ps_decode_op->u4_pic_wd), IVD_DECODE_FRAME);
+                mStride = ALIGN128(ps_decode_op->u4_pic_wd);
+                setParams(mStride, IVD_DECODE_FRAME);
             }
             if (ps_decode_op->u4_pic_wd != mWidth ||  ps_decode_op->u4_pic_ht != mHeight) {
                 mWidth = ps_decode_op->u4_pic_wd;
diff --git a/media/codec2/components/hevc/C2SoftHevcEnc.cpp b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
index 60d5875..9c26c02 100644
--- a/media/codec2/components/hevc/C2SoftHevcEnc.cpp
+++ b/media/codec2/components/hevc/C2SoftHevcEnc.cpp
@@ -1109,14 +1109,14 @@
         }
     }
 
-    std::shared_ptr<const C2GraphicView> view;
+    std::shared_ptr<C2GraphicView> view;
     std::shared_ptr<C2Buffer> inputBuffer = nullptr;
     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
     if (eos) mSignalledEos = true;
 
     if (!work->input.buffers.empty()) {
         inputBuffer = work->input.buffers[0];
-        view = std::make_shared<const C2GraphicView>(
+        view = std::make_shared<C2GraphicView>(
             inputBuffer->data().graphicBlocks().front().map().get());
         if (view->error() != C2_OK) {
             ALOGE("graphic view map err = %d", view->error());
@@ -1125,6 +1125,9 @@
             work->workletsProcessed = 1u;
             return;
         }
+        //(b/232396154)
+        //workaround for incorrect crop size in view when using surface mode
+        view->setCrop_be(C2Rect(mSize->width, mSize->height));
     }
     IHEVCE_PLUGIN_STATUS_T err = IHEVCE_EOK;
 
diff --git a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
index 9a41910..439323c 100644
--- a/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
+++ b/media/codec2/components/mpeg2/C2SoftMpeg2Dec.cpp
@@ -732,6 +732,9 @@
 void C2SoftMpeg2Dec::resetPlugin() {
     mSignalledOutputEos = false;
     mTimeStart = mTimeEnd = systemTime();
+    if (mOutBlock) {
+        mOutBlock.reset();
+    }
 }
 
 status_t C2SoftMpeg2Dec::deleteDecoder() {
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
index 54a1d0e..3bf9c48 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Dec.cpp
@@ -256,7 +256,9 @@
     mFramesConfigured = false;
     mSignalledOutputEos = false;
     mSignalledError = false;
-
+    if (mOutBlock) {
+        mOutBlock.reset();
+    }
     return C2_OK;
 }
 
diff --git a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
index 3bfec66..d5e8c56 100644
--- a/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
+++ b/media/codec2/components/mpeg4_h263/C2SoftMpeg4Enc.cpp
@@ -464,18 +464,21 @@
         }
     }
 
-    std::shared_ptr<const C2GraphicView> rView;
+    std::shared_ptr<C2GraphicView> rView;
     std::shared_ptr<C2Buffer> inputBuffer;
     bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
     if (!work->input.buffers.empty()) {
         inputBuffer = work->input.buffers[0];
-        rView = std::make_shared<const C2GraphicView>(
+        rView = std::make_shared<C2GraphicView>(
                 inputBuffer->data().graphicBlocks().front().map().get());
         if (rView->error() != C2_OK) {
             ALOGE("graphic view map err = %d", rView->error());
             work->result = rView->error();
             return;
         }
+        //(b/232396154)
+        //workaround for incorrect crop size in view when using surface mode
+        rView->setCrop_be(C2Rect(mSize->width, mSize->height));
     } else {
         fillEmptyWork(work);
         if (eos) {
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.cpp b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
index f99ee24..5700e5d 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.cpp
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.cpp
@@ -59,7 +59,7 @@
 
     addParameter(
         DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
-            .withDefault(new C2StreamPictureSizeInfo::input(0u, 320, 240))
+            .withDefault(new C2StreamPictureSizeInfo::input(0u, 64, 64))
             .withFields({
                 C2F(mSize, width).inRange(2, 2048, 2),
                 C2F(mSize, height).inRange(2, 2048, 2),
@@ -81,7 +81,7 @@
 
     addParameter(
         DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
-            .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
+            .withDefault(new C2StreamFrameRateInfo::output(0u, 1.))
             // TODO: More restriction?
             .withFields({C2F(mFrameRate, value).greaterThan(0.)})
             .withSetter(
@@ -127,10 +127,18 @@
                 C2F(mProfileLevel, profile).equalTo(
                     PROFILE_VP9_0
                 ),
-                C2F(mProfileLevel, level).equalTo(
-                    LEVEL_VP9_4_1),
+                C2F(mProfileLevel, level).oneOf({
+                        C2Config::LEVEL_VP9_1,
+                        C2Config::LEVEL_VP9_1_1,
+                        C2Config::LEVEL_VP9_2,
+                        C2Config::LEVEL_VP9_2_1,
+                        C2Config::LEVEL_VP9_3,
+                        C2Config::LEVEL_VP9_3_1,
+                        C2Config::LEVEL_VP9_4,
+                        C2Config::LEVEL_VP9_4_1,
+                }),
             })
-            .withSetter(ProfileLevelSetter)
+            .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
             .build());
 #else
     addParameter(
@@ -144,7 +152,7 @@
                 C2F(mProfileLevel, level).equalTo(
                     LEVEL_UNUSED),
             })
-            .withSetter(ProfileLevelSetter)
+            .withSetter(ProfileLevelSetter, mSize, mFrameRate, mBitrate)
             .build());
 #endif
     addParameter(
@@ -217,14 +225,81 @@
 }
 
 C2R C2SoftVpxEnc::IntfImpl::ProfileLevelSetter(bool mayBlock,
-                                               C2P<C2StreamProfileLevelInfo::output>& me) {
+                                               C2P<C2StreamProfileLevelInfo::output>& me,
+                                               const C2P<C2StreamPictureSizeInfo::input>& size,
+                                               const C2P<C2StreamFrameRateInfo::output>& frameRate,
+                                               const C2P<C2StreamBitrateInfo::output>& bitrate) {
     (void)mayBlock;
+#ifdef VP9
     if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
         me.set().profile = PROFILE_VP9_0;
     }
-    if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+    struct LevelLimits {
+        C2Config::level_t level;
+        float samplesPerSec;
+        uint64_t samples;
+        uint32_t bitrate;
+        size_t dimension;
+    };
+    constexpr LevelLimits kLimits[] = {
+            {LEVEL_VP9_1, 829440, 36864, 200000, 512},
+            {LEVEL_VP9_1_1, 2764800, 73728, 800000, 768},
+            {LEVEL_VP9_2, 4608000, 122880, 1800000, 960},
+            {LEVEL_VP9_2_1, 9216000, 245760, 3600000, 1344},
+            {LEVEL_VP9_3, 20736000, 552960, 7200000, 2048},
+            {LEVEL_VP9_3_1, 36864000, 983040, 12000000, 2752},
+            {LEVEL_VP9_4, 83558400, 2228224, 18000000, 4160},
+            {LEVEL_VP9_4_1, 160432128, 2228224, 30000000, 4160},
+    };
+
+    uint64_t samples = size.v.width * size.v.height;
+    float samplesPerSec = float(samples) * frameRate.v.value;
+    size_t dimension = std::max(size.v.width, size.v.height);
+
+    // Check if the supplied level meets the samples / bitrate requirements.
+    // If not, update the level with the lowest level meeting the requirements.
+    bool found = false;
+
+    // By default needsUpdate = false in case the supplied level does meet
+    // the requirements.
+    bool needsUpdate = false;
+    for (const LevelLimits& limit : kLimits) {
+        if (samples <= limit.samples && samplesPerSec <= limit.samplesPerSec &&
+            bitrate.v.value <= limit.bitrate && dimension <= limit.dimension) {
+            // This is the lowest level that meets the requirements, and if
+            // we haven't seen the supplied level yet, that means we don't
+            // need the update.
+            if (needsUpdate) {
+                ALOGD("Given level %x does not cover current configuration: "
+                        "adjusting to %x",
+                        me.v.level, limit.level);
+                me.set().level = limit.level;
+            }
+            found = true;
+            break;
+        }
+        if (me.v.level == limit.level) {
+            // We break out of the loop when the lowest feasible level is
+            // found. The fact that we're here means that our level doesn't
+            // meet the requirement and needs to be updated.
+            needsUpdate = true;
+        }
+    }
+    if (!found) {
+        // We set to the highest supported level.
         me.set().level = LEVEL_VP9_4_1;
     }
+#else
+    (void)size;
+    (void)frameRate;
+    (void)bitrate;
+    if (!me.F(me.v.profile).supportsAtAll(me.v.profile)) {
+        me.set().profile = PROFILE_VP8_0;
+    }
+    if (!me.F(me.v.level).supportsAtAll(me.v.level)) {
+        me.set().level = LEVEL_UNUSED;
+    }
+#endif
     return C2R::Ok();
 }
 
@@ -683,17 +758,20 @@
         return;
     }
 
-    std::shared_ptr<const C2GraphicView> rView;
+    std::shared_ptr<C2GraphicView> rView;
     std::shared_ptr<C2Buffer> inputBuffer;
     if (!work->input.buffers.empty()) {
         inputBuffer = work->input.buffers[0];
-        rView = std::make_shared<const C2GraphicView>(
+        rView = std::make_shared<C2GraphicView>(
                     inputBuffer->data().graphicBlocks().front().map().get());
         if (rView->error() != C2_OK) {
             ALOGE("graphic view map err = %d", rView->error());
             work->result = C2_CORRUPTED;
             return;
         }
+        //(b/232396154)
+        //workaround for incorrect crop size in view when using surface mode
+        rView->setCrop_be(C2Rect(mSize->width, mSize->height));
     } else {
         ALOGV("Empty input Buffer");
         uint32_t flags = 0;
diff --git a/media/codec2/components/vpx/C2SoftVpxEnc.h b/media/codec2/components/vpx/C2SoftVpxEnc.h
index 714fadb..bfb4444 100644
--- a/media/codec2/components/vpx/C2SoftVpxEnc.h
+++ b/media/codec2/components/vpx/C2SoftVpxEnc.h
@@ -243,9 +243,10 @@
     static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::input> &oldMe,
                           C2P<C2StreamPictureSizeInfo::input> &me);
 
-    static C2R ProfileLevelSetter(
-            bool mayBlock,
-            C2P<C2StreamProfileLevelInfo::output> &me);
+    static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::output>& me,
+                                  const C2P<C2StreamPictureSizeInfo::input>& size,
+                                  const C2P<C2StreamFrameRateInfo::output>& frameRate,
+                                  const C2P<C2StreamBitrateInfo::output>& bitrate);
 
     static C2R LayeringSetter(bool mayBlock, C2P<C2StreamTemporalLayeringTuning::output>& me);
 
diff --git a/media/codec2/core/include/C2Config.h b/media/codec2/core/include/C2Config.h
index 6ff3dbc..417b261 100644
--- a/media/codec2/core/include/C2Config.h
+++ b/media/codec2/core/include/C2Config.h
@@ -2503,7 +2503,8 @@
  * Note: This parameter allows a decoder to ignore the video peek machinery and
  * to revert to its preferred behavior.
  */
-typedef C2StreamParam<C2Tuning, C2EasyEnum<C2PlatformConfig::tunnel_peek_mode_t>,
+typedef C2StreamParam<C2Tuning,
+        C2SimpleValueStruct<C2EasyEnum<C2PlatformConfig::tunnel_peek_mode_t>>,
         kParamIndexTunnelPeekMode> C2StreamTunnelPeekModeTuning;
 constexpr char C2_PARAMKEY_TUNNEL_PEEK_MODE[] =
         "output.tunnel-peek-mode";
diff --git a/media/codec2/fuzzer/C2Fuzzer.cpp b/media/codec2/fuzzer/C2Fuzzer.cpp
index e469d8b..d6793e0 100644
--- a/media/codec2/fuzzer/C2Fuzzer.cpp
+++ b/media/codec2/fuzzer/C2Fuzzer.cpp
@@ -246,7 +246,8 @@
   bufferSource->parse();
   c2_status_t status = C2_OK;
   size_t numFrames = 0;
-  while (!bufferSource->isEos()) {
+  int32_t iterationCount = 0;
+  while (!bufferSource->isEos() && ++iterationCount <= kMaxIterations) {
     uint8_t* frame = nullptr;
     size_t frameSize = 0;
     FrameData frameData = bufferSource->getFrame();
diff --git a/media/codec2/fuzzer/C2Fuzzer.h b/media/codec2/fuzzer/C2Fuzzer.h
index da76885..4e3e3ea 100644
--- a/media/codec2/fuzzer/C2Fuzzer.h
+++ b/media/codec2/fuzzer/C2Fuzzer.h
@@ -37,6 +37,7 @@
 #define C2FUZZER_ALIGN(_sz, _align) (((_sz) + ((_align)-1)) & ~((_align)-1))
 
 constexpr std::chrono::milliseconds kC2FuzzerTimeOut = 5000ms;
+constexpr int32_t kMaxIterations = 100;
 constexpr int32_t kNumberOfC2WorkItems = 8;
 constexpr uint32_t kWidthOfVideo = 3840;
 constexpr uint32_t kHeightOfVideo = 2160;
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index bd7ec0d..327717b 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -372,9 +372,8 @@
             ULock l(queueLock);
             flushedIndices.emplace_back(frameID);
         }
-        char* data = (char*)malloc(bytesCount);
-        ASSERT_NE(data, nullptr);
-        eleStream.read(data, bytesCount);
+        std::vector<char> eleData(bytesCount);
+        eleStream.read(eleData.data(), bytesCount);
         // if we have reached at the end of input stream, signal eos
         if (eleStream.gcount() < bytesCount) {
             bytesCount = eleStream.gcount();
@@ -396,12 +395,11 @@
         ASSERT_EQ(0u, view.offset());
         ASSERT_EQ((size_t)bytesCount, view.size());
 
-        memcpy(view.base(), data, bytesCount);
+        memcpy(view.base(), eleData.data(), bytesCount);
         work->input.buffers.clear();
         work->input.buffers.emplace_back(new LinearBuffer(block));
         work->worklets.clear();
         work->worklets.emplace_back(new C2Worklet);
-        free(data);
 
         std::list<std::unique_ptr<C2Work>> items;
         items.push_back(std::move(work));
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 67873fa..117d9ca 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -214,10 +214,8 @@
             calc_md5_cksum(uPlane, uvStride, cropWidth / 2, cropHeight / 2, au1_u_chksum);
             calc_md5_cksum(vPlane, uvStride, cropWidth / 2, cropHeight / 2, au1_v_chksum);
         } else if (bitDepth == 8 && layoutType == C2PlanarLayout::TYPE_YUV && colInc == 2) {
-            uint8_t* cbPlane = (uint8_t*)malloc(cropWidth * cropHeight / 4);
-            uint8_t* crPlane = (uint8_t*)malloc(cropWidth * cropHeight / 4);
-            ASSERT_NE(cbPlane, nullptr);
-            ASSERT_NE(crPlane, nullptr);
+            std::vector<uint8_t> cbPlane(cropWidth * cropHeight / 4);
+            std::vector<uint8_t> crPlane(cropWidth * cropHeight / 4);
             size_t count = 0;
             for (size_t k = 0; k < (cropHeight / 2); k++) {
                 for (size_t l = 0; l < (cropWidth); l = l + 2) {
@@ -227,10 +225,10 @@
                 }
             }
             calc_md5_cksum(yPlane, yStride, cropWidth, cropHeight, au1_y_chksum);
-            calc_md5_cksum(cbPlane, cropWidth / 2, cropWidth / 2, cropHeight / 2, au1_u_chksum);
-            calc_md5_cksum(crPlane, cropWidth / 2, cropWidth / 2, cropHeight / 2, au1_v_chksum);
-            free(cbPlane);
-            free(crPlane);
+            calc_md5_cksum(cbPlane.data(), cropWidth / 2, cropWidth / 2, cropHeight / 2,
+                           au1_u_chksum);
+            calc_md5_cksum(crPlane.data(), cropWidth / 2, cropWidth / 2, cropHeight / 2,
+                           au1_v_chksum);
         } else {
             mMd5Enable = false;
             ALOGV("Disabling MD5 chksm flag");
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 0acf7d7..9359e29 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -1582,6 +1582,10 @@
     return mOutputBufferQueue->outputBuffer(block, input, output);
 }
 
+void Codec2Client::Component::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
+    mOutputBufferQueue->pollForRenderedFrames(delta);
+}
+
 void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
         int maxDequeueCount) {
     mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index 49d9b28..2fdca29 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -23,6 +23,7 @@
 #include <C2Param.h>
 #include <C2.h>
 
+#include <gui/FrameTimestamps.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <hidl/HidlSupport.h>
 #include <utils/StrongPointer.h>
@@ -408,6 +409,9 @@
             const QueueBufferInput& input,
             QueueBufferOutput* output);
 
+    // Retrieve frame event history from the output surface.
+    void pollForRenderedFrames(FrameEventHistoryDelta* delta);
+
     // Set max dequeue count for output surface.
     void setOutputSurfaceMaxDequeueCount(int maxDequeueCount);
 
diff --git a/media/codec2/hidl/client/include/codec2/hidl/output.h b/media/codec2/hidl/client/include/codec2/hidl/output.h
index a13edf3..35a0224 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/output.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/output.h
@@ -17,6 +17,7 @@
 #ifndef CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE
 #define CODEC2_HIDL_V1_0_UTILS_OUTPUT_BUFFER_QUEUE
 
+#include <gui/FrameTimestamps.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <codec2/hidl/1.0/types.h>
 #include <codec2/hidl/1.2/types.h>
@@ -60,6 +61,9 @@
             const BnGraphicBufferProducer::QueueBufferInput& input,
             BnGraphicBufferProducer::QueueBufferOutput* output);
 
+    // Retrieve frame event history from the output surface.
+    void pollForRenderedFrames(FrameEventHistoryDelta* delta);
+
     // Call holdBufferQueueBlock() on output blocks in the given workList.
     // The OutputBufferQueue will take the ownership of output blocks.
     //
diff --git a/media/codec2/hidl/client/output.cpp b/media/codec2/hidl/client/output.cpp
index f789030..dd10691 100644
--- a/media/codec2/hidl/client/output.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -476,6 +476,12 @@
     return OK;
 }
 
+void OutputBufferQueue::pollForRenderedFrames(FrameEventHistoryDelta* delta) {
+    if (mIgbp) {
+        mIgbp->getFrameTimestamps(delta);
+    }
+}
+
 void OutputBufferQueue::holdBufferQueueBlocks(
         const std::list<std::unique_ptr<C2Work>>& workList) {
     forEachBlock(workList,
diff --git a/media/codec2/hidl/plugin/samples/Android.bp b/media/codec2/hidl/plugin/samples/Android.bp
index 32b760d..e0f8280 100644
--- a/media/codec2/hidl/plugin/samples/Android.bp
+++ b/media/codec2/hidl/plugin/samples/Android.bp
@@ -28,6 +28,7 @@
         "libGLESv1_CM",
         "libGLESv2",
         "libGLESv3",
+        "libvulkan",
         "libbase",
         "libcodec2",
         "libcutils",
diff --git a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
index 5c13b0e..c8997bb 100644
--- a/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
+++ b/media/codec2/hidl/plugin/samples/SampleFilterPlugin.cpp
@@ -417,6 +417,7 @@
         }
         std::unique_lock lock(mQueueMutex);
         mQueue.splice(mQueue.end(), *items);
+        mQueueCondition.notify_all();
         return C2_OK;
     }
 
@@ -665,6 +666,7 @@
                         grallocHandle, GraphicBuffer::CLONE_HANDLE,
                         width, height, format, 1, usage, stride);
 
+                native_handle_delete(grallocHandle);
                 std::shared_ptr<C2GraphicBlock> dstBlock;
                 C2BlockPool::local_id_t poolId = mIntf->getPoolId();
                 std::shared_ptr<C2BlockPool> pool;
@@ -683,6 +685,7 @@
                         grallocHandle, GraphicBuffer::CLONE_HANDLE,
                         width, height, format, 1, usage, stride);
 
+                native_handle_delete(grallocHandle);
                 Rect sourceCrop(0, 0, width, height);
 
                 renderengine::DisplaySettings clientCompositionDisplay;
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index b36e80a..524519c 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -85,6 +85,9 @@
         arm64: {
             src: "seccomp_policy/android.hardware.media.c2@1.2-default-arm64.policy",
         },
+        riscv64: {
+            src: "seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy",
+        },
         x86: {
             src: "seccomp_policy/android.hardware.media.c2@1.2-default-x86.policy",
         },
@@ -96,3 +99,4 @@
     // This may be removed.
     required: ["crash_dump.policy"],
 }
+
diff --git a/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
new file mode 100644
index 0000000..27f0b95
--- /dev/null
+++ b/media/codec2/hidl/services/seccomp_policy/android.hardware.media.c2@1.2-default-riscv64.policy
@@ -0,0 +1,75 @@
+# Copyright (C) 2019 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.
+
+futex: 1
+# ioctl calls are filtered via the selinux policy.
+ioctl: 1
+sched_yield: 1
+close: 1
+dup: 1
+ppoll: 1
+mprotect: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+mmap: arg2 in ~PROT_EXEC || arg2 in ~PROT_WRITE
+getuid: 1
+getrlimit: 1
+fstat: 1
+newfstatat: 1
+fstatfs: 1
+memfd_create: 1
+ftruncate: 1
+
+mremap: arg3 == 3 || arg3 == MREMAP_MAYMOVE
+munmap: 1
+prctl: 1
+writev: 1
+sigaltstack: 1
+clone: 1
+exit: 1
+lseek: 1
+rt_sigprocmask: 1
+openat: 1
+write: 1
+nanosleep: 1
+setpriority: 1
+set_tid_address: 1
+getdents64: 1
+readlinkat: 1
+read: 1
+pread64: 1
+gettimeofday: 1
+faccessat: 1
+exit_group: 1
+restart_syscall: 1
+rt_sigreturn: 1
+getrandom: 1
+madvise: 1
+
+# crash dump policy additions
+clock_gettime: 1
+getpid: 1
+gettid: 1
+pipe2: 1
+recvmsg: 1
+process_vm_readv: 1
+tgkill: 1
+rt_sigaction: 1
+rt_tgsigqueueinfo: 1
+#mprotect: arg2 in 0x1|0x2
+munmap: 1
+#mmap: arg2 in 0x1|0x2
+geteuid: 1
+getgid: 1
+getegid: 1
+getgroups: 1
+
diff --git a/media/codec2/sfplugin/Android.bp b/media/codec2/sfplugin/Android.bp
index 5a652a3..ecd5463 100644
--- a/media/codec2/sfplugin/Android.bp
+++ b/media/codec2/sfplugin/Android.bp
@@ -44,7 +44,7 @@
     ],
 
     static_libs: [
-        "SurfaceFlingerProperties",
+        "libSurfaceFlingerProperties",
     ],
 
     shared_libs: [
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index feb0876..6e183e9 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1024,7 +1024,7 @@
             C2StoreFlexiblePixelFormatDescriptorsInfo *pixelFormatInfo = nullptr;
             int vendorSdkVersion = base::GetIntProperty(
                     "ro.vendor.build.version.sdk", android_get_device_api_level());
-            if (vendorSdkVersion >= __ANDROID_API_S__ && mClient->query(
+            if (mClient->query(
                         {},
                         {C2StoreFlexiblePixelFormatDescriptorsInfo::PARAM_TYPE},
                         C2_MAY_BLOCK,
@@ -1085,8 +1085,7 @@
             } else {
                 if ((config->mDomain & Config::IS_ENCODER) || !surface) {
                     if (vendorSdkVersion < __ANDROID_API_S__ &&
-                            (format == COLOR_FormatYUV420Flexible ||
-                             format == COLOR_FormatYUV420Planar ||
+                            (format == COLOR_FormatYUV420Planar ||
                              format == COLOR_FormatYUV420PackedPlanar ||
                              format == COLOR_FormatYUV420SemiPlanar ||
                              format == COLOR_FormatYUV420PackedSemiPlanar)) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index c7ab360..36b2b3f 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -899,7 +899,7 @@
     }
 
     // TODO: revisit this after C2Fence implementation.
-    android::IGraphicBufferProducer::QueueBufferInput qbi(
+    IGraphicBufferProducer::QueueBufferInput qbi(
             timestampNs,
             false, // droppable
             dataSpace,
@@ -963,9 +963,9 @@
     }
     SetMetadataToGralloc4Handle(dataSpace, hdrStaticInfo, hdrDynamicInfo, block.handle());
 
-    // we don't have dirty regions
-    qbi.setSurfaceDamage(Region::INVALID_REGION);
-    android::IGraphicBufferProducer::QueueBufferOutput qbo;
+    qbi.setSurfaceDamage(Region::INVALID_REGION); // we don't have dirty regions
+    qbi.getFrameTimestamps = true; // we need to know when a frame is rendered
+    IGraphicBufferProducer::QueueBufferOutput qbo;
     status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo);
     if (result != OK) {
         ALOGI("[%s] queueBuffer failed: %d", mName, result);
@@ -983,11 +983,107 @@
 
     int64_t mediaTimeUs = 0;
     (void)buffer->meta()->findInt64("timeUs", &mediaTimeUs);
-    mCCodecCallback->onOutputFramesRendered(mediaTimeUs, timestampNs);
+    trackReleasedFrame(qbo, mediaTimeUs, timestampNs);
+    processRenderedFrames(qbo.frameTimestamps);
 
     return OK;
 }
 
+void CCodecBufferChannel::initializeFrameTrackingFor(ANativeWindow * window) {
+    int hasPresentFenceTimes = 0;
+    window->query(window, NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &hasPresentFenceTimes);
+    mHasPresentFenceTimes = hasPresentFenceTimes == 1;
+    if (mHasPresentFenceTimes) {
+        ALOGI("Using latch times for frame rendered signals - present fences not supported");
+    }
+    mTrackedFrames.clear();
+}
+
+void CCodecBufferChannel::trackReleasedFrame(const IGraphicBufferProducer::QueueBufferOutput& qbo,
+                                             int64_t mediaTimeUs, int64_t desiredRenderTimeNs) {
+    // If the render time is earlier than now, then we're suggesting it should be rendered ASAP,
+    // so track the frame as if the desired render time is now.
+    int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+    if (desiredRenderTimeNs < nowNs) {
+        desiredRenderTimeNs = nowNs;
+    }
+    // We've just queued a frame to the surface, so keep track of it and later check to see if it is
+    // actually rendered.
+    TrackedFrame frame;
+    frame.number = qbo.nextFrameNumber - 1;
+    frame.mediaTimeUs = mediaTimeUs;
+    frame.desiredRenderTimeNs = desiredRenderTimeNs;
+    frame.latchTime = -1;
+    frame.presentFence = nullptr;
+    mTrackedFrames.push_back(frame);
+}
+
+void CCodecBufferChannel::processRenderedFrames(const FrameEventHistoryDelta& deltas) {
+    // Grab the latch times and present fences from the frame event deltas
+    for (const auto& delta : deltas) {
+        for (auto& frame : mTrackedFrames) {
+            if (delta.getFrameNumber() == frame.number) {
+                delta.getLatchTime(&frame.latchTime);
+                delta.getDisplayPresentFence(&frame.presentFence);
+            }
+        }
+    }
+
+    // Scan all frames and check to see if the frames that SHOULD have been rendered by now, have,
+    // in fact, been rendered.
+    int64_t nowNs = systemTime(SYSTEM_TIME_MONOTONIC);
+    while (!mTrackedFrames.empty()) {
+        TrackedFrame & frame = mTrackedFrames.front();
+        // Frames that should have been rendered at least 100ms in the past are checked
+        if (frame.desiredRenderTimeNs > nowNs - 100*1000*1000LL) {
+            break;
+        }
+
+        // If we don't have a render time by now, then consider the frame as dropped
+        int64_t renderTimeNs = getRenderTimeNs(frame);
+        if (renderTimeNs != -1) {
+            mCCodecCallback->onOutputFramesRendered(frame.mediaTimeUs, renderTimeNs);
+        }
+        mTrackedFrames.pop_front();
+    }
+}
+
+int64_t CCodecBufferChannel::getRenderTimeNs(const TrackedFrame& frame) {
+    // If the device doesn't have accurate present fence times, then use the latch time as a proxy
+    if (!mHasPresentFenceTimes) {
+        if (frame.latchTime == -1) {
+            ALOGD("no latch time for frame %d", (int) frame.number);
+            return -1;
+        }
+        return frame.latchTime;
+    }
+
+    if (frame.presentFence == nullptr) {
+        ALOGW("no present fence for frame %d", (int) frame.number);
+        return -1;
+    }
+
+    nsecs_t actualRenderTimeNs = frame.presentFence->getSignalTime();
+
+    if (actualRenderTimeNs == Fence::SIGNAL_TIME_INVALID) {
+        ALOGW("invalid signal time for frame %d", (int) frame.number);
+        return -1;
+    }
+
+    if (actualRenderTimeNs == Fence::SIGNAL_TIME_PENDING) {
+        ALOGD("present fence has not fired for frame %d", (int) frame.number);
+        return -1;
+    }
+
+    return actualRenderTimeNs;
+}
+
+void CCodecBufferChannel::pollForRenderedBuffers() {
+    FrameEventHistoryDelta delta;
+    mComponent->pollForRenderedFrames(&delta);
+    processRenderedFrames(delta);
+}
+
 status_t CCodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
     ALOGV("[%s] discardBuffer: %p", mName, buffer.get());
     bool released = false;
@@ -1612,6 +1708,8 @@
         Mutexed<Output>::Locked output(mOutput);
         output->buffers.reset();
     }
+    // reset the frames that are being tracked for onFrameRendered callbacks
+    mTrackedFrames.clear();
 }
 
 void CCodecBufferChannel::release() {
@@ -1680,6 +1778,8 @@
             output->buffers->flushStash();
         }
     }
+    // reset the frames that are being tracked for onFrameRendered callbacks
+    mTrackedFrames.clear();
 }
 
 void CCodecBufferChannel::onWorkDone(
@@ -2153,6 +2253,7 @@
         Mutexed<OutputSurface>::Locked output(mOutputSurface);
         output->surface = newSurface;
         output->generation = generation;
+        initializeFrameTrackingFor(static_cast<ANativeWindow *>(newSurface.get()));
     }
 
     if (oldSurface && pushBlankBuffer) {
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.h b/media/codec2/sfplugin/CCodecBufferChannel.h
index a52d4dc..e2e55b9 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.h
+++ b/media/codec2/sfplugin/CCodecBufferChannel.h
@@ -18,6 +18,7 @@
 
 #define CCODEC_BUFFER_CHANNEL_H_
 
+#include <deque>
 #include <map>
 #include <memory>
 #include <vector>
@@ -88,6 +89,7 @@
             const sp<MediaCodecBuffer> &buffer) override;
     virtual status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
+    virtual void pollForRenderedBuffers() override;
     virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
     virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
     virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
@@ -260,6 +262,14 @@
         bool mRunning;
     };
 
+    struct TrackedFrame {
+        uint64_t number;
+        int64_t mediaTimeUs;
+        int64_t desiredRenderTimeNs;
+        nsecs_t latchTime;
+        sp<Fence> presentFence;
+    };
+
     void feedInputBufferIfAvailable();
     void feedInputBufferIfAvailableInternal();
     status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer,
@@ -272,6 +282,12 @@
     void ensureDecryptDestination(size_t size);
     int32_t getHeapSeqNum(const sp<hardware::HidlMemory> &memory);
 
+    void initializeFrameTrackingFor(ANativeWindow * window);
+    void trackReleasedFrame(const IGraphicBufferProducer::QueueBufferOutput& qbo,
+                            int64_t mediaTimeUs, int64_t desiredRenderTimeNs);
+    void processRenderedFrames(const FrameEventHistoryDelta& delta);
+    int64_t getRenderTimeNs(const TrackedFrame& frame);
+
     QueueSync mSync;
     sp<MemoryDealer> mDealer;
     sp<IMemory> mDecryptDestination;
@@ -313,6 +329,9 @@
 
     sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
 
+    std::deque<TrackedFrame> mTrackedFrames;
+    bool mHasPresentFenceTimes;
+
     struct OutputSurface {
         sp<Surface> surface;
         uint32_t generation;
diff --git a/media/codec2/sfplugin/CCodecBuffers.h b/media/codec2/sfplugin/CCodecBuffers.h
index c8e9930..6335f13 100644
--- a/media/codec2/sfplugin/CCodecBuffers.h
+++ b/media/codec2/sfplugin/CCodecBuffers.h
@@ -72,7 +72,7 @@
     virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {}
 
     /**
-     * Return number of buffers the client owns.
+     * Return number of buffers owned by the client or the component.
      */
     virtual size_t numActiveSlots() const = 0;
 
@@ -595,8 +595,7 @@
     void flush();
 
     /**
-     * Return the number of buffers that are sent to the client but not released
-     * yet.
+     * Return the number of buffers that are sent to the client or the component.
      */
     size_t numActiveSlots() const;
 
@@ -716,8 +715,7 @@
     void grow(size_t newSize, std::function<sp<Codec2Buffer>()> alloc);
 
     /**
-     * Return the number of buffers that are sent to the client but not released
-     * yet.
+     * Return the number of buffers that are sent to the client or the component.
      */
     size_t numActiveSlots() const;
 
diff --git a/media/codec2/sfplugin/CCodecConfig.cpp b/media/codec2/sfplugin/CCodecConfig.cpp
index 5208be6..0253815 100644
--- a/media/codec2/sfplugin/CCodecConfig.cpp
+++ b/media/codec2/sfplugin/CCodecConfig.cpp
@@ -389,7 +389,7 @@
             // read back always as int
             float value;
             if (v.get(&value)) {
-                return (int32_t)value;
+                return (int32_t) (value + 0.5);
             }
             return C2Value();
         }));
diff --git a/media/codec2/sfplugin/Codec2Buffer.cpp b/media/codec2/sfplugin/Codec2Buffer.cpp
index 55e0c45..8f0f1c9 100644
--- a/media/codec2/sfplugin/Codec2Buffer.cpp
+++ b/media/codec2/sfplugin/Codec2Buffer.cpp
@@ -22,6 +22,7 @@
 
 #include <aidl/android/hardware/graphics/common/Cta861_3.h>
 #include <aidl/android/hardware/graphics/common/Smpte2086.h>
+#include <android-base/no_destructor.h>
 #include <android-base/properties.h>
 #include <android/hardware/cas/native/1.0/types.h>
 #include <android/hardware/drm/1.0/types.h>
@@ -533,7 +534,7 @@
                         * align(mHeight, 64) / plane.rowSampling;
             }
 
-            if (minPtr == mView.data()[0] && (maxPtr - minPtr + 1) <= planeSize) {
+            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
@@ -545,8 +546,7 @@
                     mediaImage->mPlane[i].mHorizSubsampling = plane.colSampling;
                     mediaImage->mPlane[i].mVertSubsampling = plane.rowSampling;
                 }
-                mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr),
-                                       maxPtr - minPtr + 1);
+                mWrapped = new ABuffer(const_cast<uint8_t *>(minPtr), maxPtr - minPtr);
                 ALOGV("Converter: wrapped (capacity=%zu)", mWrapped->capacity());
             }
         }
@@ -843,6 +843,10 @@
         }
     }
     sp<ABuffer> aBuffer(alloc(align(width, 16) * align(height, 16) * bpp / 8));
+    if (aBuffer == nullptr) {
+        ALOGD("%s: failed to allocate buffer", __func__);
+        return nullptr;
+    }
     return new ConstGraphicBlockBuffer(
             format,
             aBuffer,
@@ -1015,8 +1019,8 @@
 namespace {
 
 sp<IMapper4> GetMapper4() {
-    static sp<IMapper4> sMapper = IMapper4::getService();
-    return sMapper;
+    static ::android::base::NoDestructor<sp<IMapper4>> sMapper(IMapper4::getService());
+    return *sMapper;
 }
 
 class Gralloc4Buffer {
diff --git a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
index ef5800d..332d3ac 100644
--- a/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
+++ b/media/codec2/sfplugin/utils/Codec2CommonUtils.cpp
@@ -38,7 +38,7 @@
            !strcmp(deviceCodeName, "Tiramisu");
 }
 
-bool isVendorApiOrFirstApiAtLeastT() {
+static bool isP010Allowed() {
     // The first SDK the device shipped with.
     static const int32_t kProductFirstApiLevel =
         base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
@@ -47,6 +47,17 @@
     // to signal which VSR requirements they conform to even if the first device SDK was higher.
     static const int32_t kBoardFirstApiLevel =
         base::GetIntProperty<int32_t>("ro.board.first_api_level", 0);
+
+    // Some devices that launched prior to Android S may not support P010 correctly, even
+    // though they may advertise it as supported.
+    if (kProductFirstApiLevel != 0 && kProductFirstApiLevel < __ANDROID_API_S__) {
+        return false;
+    }
+
+    if (kBoardFirstApiLevel != 0 && kBoardFirstApiLevel < __ANDROID_API_S__) {
+        return false;
+    }
+
     static const int32_t kBoardApiLevel =
         base::GetIntProperty<int32_t>("ro.board.api_level", 0);
 
@@ -67,7 +78,7 @@
     // API alone. For now limit P010 to devices that launched with Android T or known to conform
     // to Android T VSR (as opposed to simply limiting to a T vendor image).
     if (format == (AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010 &&
-            !isVendorApiOrFirstApiAtLeastT()) {
+            !isP010Allowed()) {
         return false;
     }
 
diff --git a/media/codec2/tests/Android.bp b/media/codec2/tests/Android.bp
index 9c3ba4d..2217235 100644
--- a/media/codec2/tests/Android.bp
+++ b/media/codec2/tests/Android.bp
@@ -36,6 +36,8 @@
 cc_test {
     name: "codec2_vndk_test",
     test_suites: ["device-tests"],
+    // This test doesn't seem to support isolated with current assumption
+    isolated: false,
 
     srcs: [
         "C2_test.cpp",
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index bc4053d..f272499 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -54,6 +54,10 @@
     static_assert((~C2MemoryUsage::PLATFORM_MASK & PASSTHROUGH_USAGE_MASK) == 0, "");
 } // unnamed
 
+static bool isAtLeastT() {
+    return android_get_device_api_level() >= __ANDROID_API_T__;
+}
+
 C2MemoryUsage C2AndroidMemoryUsage::FromGrallocUsage(uint64_t usage) {
     // gralloc does not support WRITE_PROTECTED
     return C2MemoryUsage(
@@ -702,6 +706,14 @@
         }
 
         case static_cast<uint32_t>(PixelFormat4::YCBCR_P010): {
+            // In Android T, P010 is relaxed to allow arbitrary stride for the Y and UV planes,
+            // try locking with the gralloc4 mapper first.
+            c2_status_t status = Gralloc4Mapper_lock(
+                    const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
+            if (status == C2_OK) {
+                break;
+            }
+
             void *pointer = nullptr;
             status_t err = GraphicBufferMapper::get().lock(
                     const_cast<native_handle_t *>(mBuffer), grallocUsage, rect, &pointer);
@@ -760,10 +772,12 @@
         default: {
             // We don't know what it is, let's try to lock it with gralloc4
             android_ycbcr ycbcrLayout;
-            c2_status_t status = Gralloc4Mapper_lock(
-                    const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
-            if (status == C2_OK) {
-                break;
+            if (isAtLeastT()) {
+                c2_status_t status = Gralloc4Mapper_lock(
+                        const_cast<native_handle_t*>(mBuffer), grallocUsage, rect, layout, addr);
+                if (status == C2_OK) {
+                    break;
+                }
             }
 
             // fallback to lockYCbCr
diff --git a/media/codec2/vndk/C2Fence.cpp b/media/codec2/vndk/C2Fence.cpp
index 0b556aa..aa908a8 100644
--- a/media/codec2/vndk/C2Fence.cpp
+++ b/media/codec2/vndk/C2Fence.cpp
@@ -186,7 +186,7 @@
 class _C2FenceFactory::SyncFenceImpl : public C2Fence::Impl {
 public:
     virtual c2_status_t wait(c2_nsecs_t timeoutNs) {
-        c2_nsecs_t timeoutMs = timeoutNs / 1000;
+        int64_t timeoutMs = timeoutNs / 1000000;
         if (timeoutMs > INT_MAX) {
             timeoutMs = INT_MAX;
         }
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index c510fca..6bcad4a 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -238,7 +238,7 @@
      *   - Local migration on blockpool side will be done automatically by
      *     blockpool.
      *   - Before attachBuffer(), BeginAttachBlockToBufferQueue() should be called
-     *     to test eligiblity.
+     *     to test eligibility.
      *   - After attachBuffer() is called, EndAttachBlockToBufferQueue() should
      *     be called. This will set "held" status to true. If it returned
      *     false, cancelBuffer() should be called.
diff --git a/media/janitors/avic_OWNERS b/media/janitors/avic_OWNERS
new file mode 100644
index 0000000..eca9978
--- /dev/null
+++ b/media/janitors/avic_OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 1344
+# gerrit owner/approvers in the AVIC team
+arifdikici@google.com
+dichenzhang@google.com
+kyslov@google.com
+richardxie@google.com
diff --git a/media/libaaudio/Android.bp b/media/libaaudio/Android.bp
index add28e0..4b417a7 100644
--- a/media/libaaudio/Android.bp
+++ b/media/libaaudio/Android.bp
@@ -36,6 +36,9 @@
     symbol_file: "src/libaaudio.map.txt",
     first_version: "26",
     unversioned_until: "current",
+    export_header_libs: [
+        "libAAudio_headers",
+    ],
 }
 
 cc_library_headers {
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 6fff568..4affaed 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -108,7 +108,7 @@
     aaudio_result_t    outputError = AAUDIO_OK;
 
     GlitchAnalyzer     sineAnalyzer;
-    PulseLatencyAnalyzer echoAnalyzer;
+    WhiteNoiseLatencyAnalyzer echoAnalyzer;
     AudioRecording     audioRecording;
     LoopbackProcessor *loopbackProcessor;
 
diff --git a/media/libaaudio/fuzzer/Android.bp b/media/libaaudio/fuzzer/Android.bp
index 2a12191..3393930 100644
--- a/media/libaaudio/fuzzer/Android.bp
+++ b/media/libaaudio/fuzzer/Android.bp
@@ -25,6 +25,9 @@
 
 cc_fuzz {
     name: "libaaudio_fuzzer",
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     srcs: [
         "libaaudio_fuzzer.cpp",
     ],
@@ -36,10 +39,10 @@
         "libaudiomanager",
         "libaudiopolicy",
         "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
         "libutils",
     ],
     static_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "liblog",
         "libcutils",
         "libaaudio",
diff --git a/media/libaaudio/include/aaudio/AAudio.h b/media/libaaudio/include/aaudio/AAudio.h
index 2ff9f5a..0c4a8f7 100644
--- a/media/libaaudio/include/aaudio/AAudio.h
+++ b/media/libaaudio/include/aaudio/AAudio.h
@@ -40,7 +40,7 @@
 /**
  * This is used to represent a value that has not been specified.
  * For example, an application could use {@link #AAUDIO_UNSPECIFIED} to indicate
- * that is did not not care what the specific value of a parameter was
+ * that it did not care what the specific value of a parameter was
  * and would accept whatever it was given.
  */
 #define AAUDIO_UNSPECIFIED           0
diff --git a/media/libaaudio/src/Android.bp b/media/libaaudio/src/Android.bp
index 363d219..4c5fc71 100644
--- a/media/libaaudio/src/Android.bp
+++ b/media/libaaudio/src/Android.bp
@@ -134,6 +134,10 @@
 cc_library {
     name: "libaaudio_internal",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     local_include_dirs: [
         "binding",
         "client",
@@ -167,7 +171,6 @@
         "libbinder",
         "framework-permission-aidl-cpp",
         "aaudio-aidl-cpp",
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
     ],
@@ -260,7 +263,7 @@
         "binding/aidl/aaudio/IAAudioService.aidl",
     ],
     imports: [
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
         "audioclient-types-aidl",
         "shared-file-region-aidl",
         "framework-permission-aidl",
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index 1efccb1..f5cc2be 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -25,6 +25,7 @@
 #include "client/AudioStreamInternalCapture.h"
 #include "utility/AudioClock.h"
 
+#undef ATRACE_TAG
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 #include <utils/Trace.h>
 
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 90ff4a5..938079b 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -566,9 +566,7 @@
                                       int64_t *timeNanoseconds)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    if (framePosition == nullptr) {
-        return AAUDIO_ERROR_NULL;
-    } else if (timeNanoseconds == nullptr) {
+    if (framePosition == nullptr || timeNanoseconds == nullptr) {
         return AAUDIO_ERROR_NULL;
     } else if (clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) {
         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index 8b7b75e..31fd011 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -83,7 +83,6 @@
     switch (mSessionId) {
         case AAUDIO_SESSION_ID_NONE:
         case AAUDIO_SESSION_ID_ALLOCATE:
-            break;
         default:
             break;
     }
diff --git a/media/libaaudio/tests/test_attributes.cpp b/media/libaaudio/tests/test_attributes.cpp
index b88d562..e5676a7 100644
--- a/media/libaaudio/tests/test_attributes.cpp
+++ b/media/libaaudio/tests/test_attributes.cpp
@@ -20,6 +20,7 @@
 // "test_aaudio_attributes.cpp". That other file is more current.
 // So these tests could be deleted.
 
+#include <memory>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -40,7 +41,7 @@
                             int privacyMode = DONT_SET,
                             aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT) {
 
-    float *buffer = new float[kNumFrames * kChannelCount];
+    std::unique_ptr<float[]> buffer(new float[kNumFrames * kChannelCount]);
 
     AAudioStreamBuilder *aaudioBuilder = nullptr;
     AAudioStream *aaudioStream = nullptr;
@@ -109,16 +110,15 @@
 
     if (direction == AAUDIO_DIRECTION_INPUT) {
         EXPECT_EQ(kNumFrames,
-                  AAudioStream_read(aaudioStream, buffer, kNumFrames, kNanosPerSecond));
+                  AAudioStream_read(aaudioStream, buffer.get(), kNumFrames, kNanosPerSecond));
     } else {
         EXPECT_EQ(kNumFrames,
-                  AAudioStream_write(aaudioStream, buffer, kNumFrames, kNanosPerSecond));
+                  AAudioStream_write(aaudioStream, buffer.get(), kNumFrames, kNanosPerSecond));
     }
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream));
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
-    delete[] buffer;
 }
 
 static const aaudio_usage_t sUsages[] = {
diff --git a/media/libaaudio/tests/test_recovery.cpp b/media/libaaudio/tests/test_recovery.cpp
index 6e89f83..11331af 100644
--- a/media/libaaudio/tests/test_recovery.cpp
+++ b/media/libaaudio/tests/test_recovery.cpp
@@ -16,6 +16,7 @@
 
 // Play silence and recover from dead servers or disconnected devices.
 
+#include <memory>
 #include <stdio.h>
 
 #include <aaudio/AAudio.h>
@@ -32,7 +33,6 @@
     int32_t triesLeft = 3;
     int32_t bufferCapacity;
     int32_t framesPerBurst = 0;
-    float *buffer = nullptr;
 
     int32_t actualChannelCount = 0;
     int32_t actualSampleRate = 0;
@@ -83,7 +83,7 @@
         bufferCapacity, framesPerBurst);
 
         int samplesPerBurst = framesPerBurst * actualChannelCount;
-        buffer = new float[samplesPerBurst];
+        std::unique_ptr<float[]> buffer(new float[samplesPerBurst]);
 
         result = AAudioStream_requestStart(aaudioStream);
         if (result != AAUDIO_OK) {
@@ -98,7 +98,7 @@
         int64_t printAt = actualSampleRate;
         while (result == AAUDIO_OK && framesTotal < framesMax) {
             int32_t framesWritten = AAudioStream_write(aaudioStream,
-                                                       buffer, framesPerBurst,
+                                                       buffer.get(), framesPerBurst,
                                                        DEFAULT_TIMEOUT_NANOS);
             if (framesWritten < 0) {
                 result = framesWritten;
@@ -134,6 +134,5 @@
         AAudioStream_close(aaudioStream);
     }
     AAudioStreamBuilder_delete(aaudioBuilder);
-    delete[] buffer;
     printf("          result = %d = %s\n", result, AAudio_convertResultToText(result));
 }
diff --git a/media/libaaudio/tests/test_session_id.cpp b/media/libaaudio/tests/test_session_id.cpp
index 3f7d4fc..5968b5d 100644
--- a/media/libaaudio/tests/test_session_id.cpp
+++ b/media/libaaudio/tests/test_session_id.cpp
@@ -16,6 +16,7 @@
 
 // Test AAudio SessionId, which is used to associate Effects with a stream
 
+#include <memory>
 #include <stdio.h>
 #include <unistd.h>
 
@@ -29,7 +30,7 @@
 // Test AAUDIO_SESSION_ID_NONE default
 static void checkSessionIdNone(aaudio_performance_mode_t perfMode) {
 
-    float *buffer = new float[kNumFrames * kChannelCount];
+    std::unique_ptr<float[]> buffer(new float[kNumFrames * kChannelCount]);
 
     AAudioStreamBuilder *aaudioBuilder = nullptr;
 
@@ -51,12 +52,12 @@
 
     ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(aaudioStream1));
 
-    ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1, buffer, kNumFrames, kNanosPerSecond));
+    ASSERT_EQ(kNumFrames,
+              AAudioStream_write(aaudioStream1, buffer.get(), kNumFrames, kNanosPerSecond));
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
-    delete[] buffer;
     AAudioStreamBuilder_delete(aaudioBuilder);
 }
 
@@ -72,7 +73,7 @@
 static void checkSessionIdAllocate(aaudio_performance_mode_t perfMode,
                                    aaudio_direction_t direction) {
 
-    float *buffer = new float[kNumFrames * kChannelCount];
+    std::unique_ptr<float[]> buffer(new float[kNumFrames * kChannelCount]);
 
     AAudioStreamBuilder *aaudioBuilder = nullptr;
 
@@ -106,10 +107,10 @@
 
     if (direction == AAUDIO_DIRECTION_INPUT) {
         ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream1,
-                                                buffer, kNumFrames, kNanosPerSecond));
+                                                buffer.get(), kNumFrames, kNanosPerSecond));
     } else {
         ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream1,
-                                         buffer, kNumFrames, kNanosPerSecond));
+                                         buffer.get(), kNumFrames, kNanosPerSecond));
     }
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream1));
@@ -135,10 +136,10 @@
 
     if (otherDirection == AAUDIO_DIRECTION_INPUT) {
         ASSERT_EQ(kNumFrames, AAudioStream_read(aaudioStream2,
-                                                 buffer, kNumFrames, kNanosPerSecond));
+                                                 buffer.get(), kNumFrames, kNanosPerSecond));
     } else {
         ASSERT_EQ(kNumFrames, AAudioStream_write(aaudioStream2,
-                                                 buffer, kNumFrames, kNanosPerSecond));
+                                                 buffer.get(), kNumFrames, kNanosPerSecond));
     }
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_requestStop(aaudioStream2));
@@ -147,7 +148,6 @@
 
 
     EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream1));
-    delete[] buffer;
     AAudioStreamBuilder_delete(aaudioBuilder);
 }
 
diff --git a/media/libaudioclient/AidlConversion.cpp b/media/libaudioclient/AidlConversion.cpp
index 4133bd0..b32667e 100644
--- a/media/libaudioclient/AidlConversion.cpp
+++ b/media/libaudioclient/AidlConversion.cpp
@@ -42,9 +42,6 @@
 using media::audio::common::AudioDeviceAddress;
 using media::audio::common::AudioDeviceDescription;
 using media::audio::common::AudioDeviceType;
-using media::audio::common::AudioEncapsulationMetadataType;
-using media::audio::common::AudioEncapsulationMode;
-using media::audio::common::AudioEncapsulationType;
 using media::audio::common::AudioFormatDescription;
 using media::audio::common::AudioFormatType;
 using media::audio::common::AudioGain;
@@ -69,246 +66,6 @@
 using media::audio::common::Int;
 using media::audio::common::PcmType;
 
-namespace {
-
-enum class Direction {
-    INPUT, OUTPUT
-};
-
-ConversionResult<Direction> direction(media::AudioPortRole role, media::AudioPortType type) {
-    switch (type) {
-        case media::AudioPortType::NONE:
-        case media::AudioPortType::SESSION:
-            break;  // must be listed  -Werror,-Wswitch
-        case media::AudioPortType::DEVICE:
-            switch (role) {
-                case media::AudioPortRole::NONE:
-                     break;  // must be listed  -Werror,-Wswitch
-                case media::AudioPortRole::SOURCE:
-                    return Direction::INPUT;
-                case media::AudioPortRole::SINK:
-                    return Direction::OUTPUT;
-            }
-            break;
-        case media::AudioPortType::MIX:
-            switch (role) {
-                case media::AudioPortRole::NONE:
-                     break;  // must be listed  -Werror,-Wswitch
-                case media::AudioPortRole::SOURCE:
-                    return Direction::OUTPUT;
-                case media::AudioPortRole::SINK:
-                    return Direction::INPUT;
-            }
-            break;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<Direction> direction(audio_port_role_t role, audio_port_type_t type) {
-    switch (type) {
-        case AUDIO_PORT_TYPE_NONE:
-        case AUDIO_PORT_TYPE_SESSION:
-            break;  // must be listed  -Werror,-Wswitch
-        case AUDIO_PORT_TYPE_DEVICE:
-            switch (role) {
-                case AUDIO_PORT_ROLE_NONE:
-                     break;  // must be listed  -Werror,-Wswitch
-                case AUDIO_PORT_ROLE_SOURCE:
-                    return Direction::INPUT;
-                case AUDIO_PORT_ROLE_SINK:
-                    return Direction::OUTPUT;
-            }
-            break;
-        case AUDIO_PORT_TYPE_MIX:
-            switch (role) {
-                case AUDIO_PORT_ROLE_NONE:
-                     break;  // must be listed  -Werror,-Wswitch
-                case AUDIO_PORT_ROLE_SOURCE:
-                    return Direction::OUTPUT;
-                case AUDIO_PORT_ROLE_SINK:
-                    return Direction::INPUT;
-            }
-            break;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-}  // namespace
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-// Converters
-
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize) {
-    if (aidl.size() > maxSize - 1) {
-        return BAD_VALUE;
-    }
-    aidl.copy(dest, aidl.size());
-    dest[aidl.size()] = '\0';
-    return OK;
-}
-
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize) {
-    if (legacy == nullptr) {
-        return unexpected(BAD_VALUE);
-    }
-    if (strnlen(legacy, maxSize) == maxSize) {
-        // No null-terminator.
-        return unexpected(BAD_VALUE);
-    }
-    return std::string(legacy);
-}
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_module_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_io_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_port_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl) {
-    return convertReinterpret<audio_patch_handle_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl) {
-    return convertReinterpret<audio_unique_id_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl) {
-    return convertReinterpret<audio_hw_sync_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl) {
-    return convertReinterpret<pid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl) {
-    return convertReinterpret<uid_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl) {
-    return String16(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy) {
-    return std::string(String8(legacy).c_str());
-}
-
-// TODO b/182392769: create an optional -> optional util
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl) {
-    if (!aidl.has_value()) {
-        return std::nullopt;
-    }
-    ConversionResult<String16> conversion =
-        VALUE_OR_RETURN(aidl2legacy_string_view_String16(aidl.value()));
-    return conversion.value();
-}
-
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy) {
-  if (!legacy.has_value()) {
-    return std::nullopt;
-  }
-  ConversionResult<std::string> conversion =
-      VALUE_OR_RETURN(legacy2aidl_String16_string(legacy.value()));
-  return conversion.value();
-}
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl) {
-    return String8(aidl.data(), aidl.size());
-}
-
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy) {
-    return std::string(legacy.c_str());
-}
-
-ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
-        media::AudioIoConfigEvent aidl) {
-    switch (aidl) {
-        case media::AudioIoConfigEvent::OUTPUT_REGISTERED:
-            return AUDIO_OUTPUT_REGISTERED;
-        case media::AudioIoConfigEvent::OUTPUT_OPENED:
-            return AUDIO_OUTPUT_OPENED;
-        case media::AudioIoConfigEvent::OUTPUT_CLOSED:
-            return AUDIO_OUTPUT_CLOSED;
-        case media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED:
-            return AUDIO_OUTPUT_CONFIG_CHANGED;
-        case media::AudioIoConfigEvent::INPUT_REGISTERED:
-            return AUDIO_INPUT_REGISTERED;
-        case media::AudioIoConfigEvent::INPUT_OPENED:
-            return AUDIO_INPUT_OPENED;
-        case media::AudioIoConfigEvent::INPUT_CLOSED:
-            return AUDIO_INPUT_CLOSED;
-        case media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED:
-            return AUDIO_INPUT_CONFIG_CHANGED;
-        case media::AudioIoConfigEvent::CLIENT_STARTED:
-            return AUDIO_CLIENT_STARTED;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
-        audio_io_config_event_t legacy) {
-    switch (legacy) {
-        case AUDIO_OUTPUT_REGISTERED:
-            return media::AudioIoConfigEvent::OUTPUT_REGISTERED;
-        case AUDIO_OUTPUT_OPENED:
-            return media::AudioIoConfigEvent::OUTPUT_OPENED;
-        case AUDIO_OUTPUT_CLOSED:
-            return media::AudioIoConfigEvent::OUTPUT_CLOSED;
-        case AUDIO_OUTPUT_CONFIG_CHANGED:
-            return media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED;
-        case AUDIO_INPUT_REGISTERED:
-            return media::AudioIoConfigEvent::INPUT_REGISTERED;
-        case AUDIO_INPUT_OPENED:
-            return media::AudioIoConfigEvent::INPUT_OPENED;
-        case AUDIO_INPUT_CLOSED:
-            return media::AudioIoConfigEvent::INPUT_CLOSED;
-        case AUDIO_INPUT_CONFIG_CHANGED:
-            return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
-        case AUDIO_CLIENT_STARTED:
-            return media::AudioIoConfigEvent::CLIENT_STARTED;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<audio_port_role_t> aidl2legacy_AudioPortRole_audio_port_role_t(
         media::AudioPortRole aidl) {
     switch (aidl) {
@@ -365,1507 +122,97 @@
     return unexpected(BAD_VALUE);
 }
 
-namespace {
-
-namespace detail {
-using AudioChannelBitPair = std::pair<audio_channel_mask_t, int>;
-using AudioChannelBitPairs = std::vector<AudioChannelBitPair>;
-using AudioChannelPair = std::pair<audio_channel_mask_t, AudioChannelLayout>;
-using AudioChannelPairs = std::vector<AudioChannelPair>;
-using AudioDevicePair = std::pair<audio_devices_t, AudioDeviceDescription>;
-using AudioDevicePairs = std::vector<AudioDevicePair>;
-using AudioFormatPair = std::pair<audio_format_t, AudioFormatDescription>;
-using AudioFormatPairs = std::vector<AudioFormatPair>;
+ConversionResult<AudioPortDirection> portDirection(
+        media::AudioPortRole role, media::AudioPortType type) {
+    audio_port_role_t legacyRole = VALUE_OR_RETURN(
+            aidl2legacy_AudioPortRole_audio_port_role_t(role));
+    audio_port_type_t legacyType = VALUE_OR_RETURN(
+            aidl2legacy_AudioPortType_audio_port_type_t(type));
+    return portDirection(legacyRole, legacyType);
 }
 
-const detail::AudioChannelBitPairs& getInAudioChannelBits() {
-    static const detail::AudioChannelBitPairs pairs = {
-        { AUDIO_CHANNEL_IN_LEFT, AudioChannelLayout::CHANNEL_FRONT_LEFT },
-        { AUDIO_CHANNEL_IN_RIGHT, AudioChannelLayout::CHANNEL_FRONT_RIGHT },
-        // AUDIO_CHANNEL_IN_FRONT is at the end
-        { AUDIO_CHANNEL_IN_BACK, AudioChannelLayout::CHANNEL_BACK_CENTER },
-        // AUDIO_CHANNEL_IN_*_PROCESSED not supported
-        // AUDIO_CHANNEL_IN_PRESSURE not supported
-        // AUDIO_CHANNEL_IN_*_AXIS not supported
-        // AUDIO_CHANNEL_IN_VOICE_* not supported
-        { AUDIO_CHANNEL_IN_BACK_LEFT, AudioChannelLayout::CHANNEL_BACK_LEFT },
-        { AUDIO_CHANNEL_IN_BACK_RIGHT, AudioChannelLayout::CHANNEL_BACK_RIGHT },
-        { AUDIO_CHANNEL_IN_CENTER, AudioChannelLayout::CHANNEL_FRONT_CENTER },
-        { AUDIO_CHANNEL_IN_LOW_FREQUENCY, AudioChannelLayout::CHANNEL_LOW_FREQUENCY },
-        { AUDIO_CHANNEL_IN_TOP_LEFT, AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT },
-        { AUDIO_CHANNEL_IN_TOP_RIGHT, AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT },
-        // When going from aidl to legacy, IN_CENTER is used
-        { AUDIO_CHANNEL_IN_FRONT, AudioChannelLayout::CHANNEL_FRONT_CENTER }
-    };
-    return pairs;
-}
-
-const detail::AudioChannelPairs& getInAudioChannelPairs() {
-    static const detail::AudioChannelPairs pairs = {
-#define DEFINE_INPUT_LAYOUT(n)                                                 \
-            {                                                                  \
-                AUDIO_CHANNEL_IN_##n,                                          \
-                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
-                        AudioChannelLayout::LAYOUT_##n)                        \
-            }
-
-        DEFINE_INPUT_LAYOUT(MONO),
-        DEFINE_INPUT_LAYOUT(STEREO),
-        DEFINE_INPUT_LAYOUT(FRONT_BACK),
-        // AUDIO_CHANNEL_IN_6 not supported
-        DEFINE_INPUT_LAYOUT(2POINT0POINT2),
-        DEFINE_INPUT_LAYOUT(2POINT1POINT2),
-        DEFINE_INPUT_LAYOUT(3POINT0POINT2),
-        DEFINE_INPUT_LAYOUT(3POINT1POINT2),
-        DEFINE_INPUT_LAYOUT(5POINT1)
-#undef DEFINE_INPUT_LAYOUT
-    };
-    return pairs;
-}
-
-const detail::AudioChannelBitPairs& getOutAudioChannelBits() {
-    static const detail::AudioChannelBitPairs pairs = {
-#define DEFINE_OUTPUT_BITS(n)                                                  \
-            { AUDIO_CHANNEL_OUT_##n, AudioChannelLayout::CHANNEL_##n }
-
-        DEFINE_OUTPUT_BITS(FRONT_LEFT),
-        DEFINE_OUTPUT_BITS(FRONT_RIGHT),
-        DEFINE_OUTPUT_BITS(FRONT_CENTER),
-        DEFINE_OUTPUT_BITS(LOW_FREQUENCY),
-        DEFINE_OUTPUT_BITS(BACK_LEFT),
-        DEFINE_OUTPUT_BITS(BACK_RIGHT),
-        DEFINE_OUTPUT_BITS(FRONT_LEFT_OF_CENTER),
-        DEFINE_OUTPUT_BITS(FRONT_RIGHT_OF_CENTER),
-        DEFINE_OUTPUT_BITS(BACK_CENTER),
-        DEFINE_OUTPUT_BITS(SIDE_LEFT),
-        DEFINE_OUTPUT_BITS(SIDE_RIGHT),
-        DEFINE_OUTPUT_BITS(TOP_CENTER),
-        DEFINE_OUTPUT_BITS(TOP_FRONT_LEFT),
-        DEFINE_OUTPUT_BITS(TOP_FRONT_CENTER),
-        DEFINE_OUTPUT_BITS(TOP_FRONT_RIGHT),
-        DEFINE_OUTPUT_BITS(TOP_BACK_LEFT),
-        DEFINE_OUTPUT_BITS(TOP_BACK_CENTER),
-        DEFINE_OUTPUT_BITS(TOP_BACK_RIGHT),
-        DEFINE_OUTPUT_BITS(TOP_SIDE_LEFT),
-        DEFINE_OUTPUT_BITS(TOP_SIDE_RIGHT),
-        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_LEFT),
-        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_CENTER),
-        DEFINE_OUTPUT_BITS(BOTTOM_FRONT_RIGHT),
-        DEFINE_OUTPUT_BITS(LOW_FREQUENCY_2),
-        DEFINE_OUTPUT_BITS(FRONT_WIDE_LEFT),
-        DEFINE_OUTPUT_BITS(FRONT_WIDE_RIGHT),
-#undef DEFINE_OUTPUT_BITS
-        { AUDIO_CHANNEL_OUT_HAPTIC_A, AudioChannelLayout::CHANNEL_HAPTIC_A },
-        { AUDIO_CHANNEL_OUT_HAPTIC_B, AudioChannelLayout::CHANNEL_HAPTIC_B }
-    };
-    return pairs;
-}
-
-const detail::AudioChannelPairs& getOutAudioChannelPairs() {
-    static const detail::AudioChannelPairs pairs = {
-#define DEFINE_OUTPUT_LAYOUT(n)                                                \
-            {                                                                  \
-                AUDIO_CHANNEL_OUT_##n,                                         \
-                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>( \
-                        AudioChannelLayout::LAYOUT_##n)                        \
-            }
-
-        DEFINE_OUTPUT_LAYOUT(MONO),
-        DEFINE_OUTPUT_LAYOUT(STEREO),
-        DEFINE_OUTPUT_LAYOUT(2POINT1),
-        DEFINE_OUTPUT_LAYOUT(TRI),
-        DEFINE_OUTPUT_LAYOUT(TRI_BACK),
-        DEFINE_OUTPUT_LAYOUT(3POINT1),
-        DEFINE_OUTPUT_LAYOUT(2POINT0POINT2),
-        DEFINE_OUTPUT_LAYOUT(2POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(3POINT0POINT2),
-        DEFINE_OUTPUT_LAYOUT(3POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(QUAD),
-        DEFINE_OUTPUT_LAYOUT(QUAD_SIDE),
-        DEFINE_OUTPUT_LAYOUT(SURROUND),
-        DEFINE_OUTPUT_LAYOUT(PENTA),
-        DEFINE_OUTPUT_LAYOUT(5POINT1),
-        DEFINE_OUTPUT_LAYOUT(5POINT1_SIDE),
-        DEFINE_OUTPUT_LAYOUT(5POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(5POINT1POINT4),
-        DEFINE_OUTPUT_LAYOUT(6POINT1),
-        DEFINE_OUTPUT_LAYOUT(7POINT1),
-        DEFINE_OUTPUT_LAYOUT(7POINT1POINT2),
-        DEFINE_OUTPUT_LAYOUT(7POINT1POINT4),
-        DEFINE_OUTPUT_LAYOUT(13POINT_360RA),
-        DEFINE_OUTPUT_LAYOUT(22POINT2),
-        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_A),
-        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_A),
-        DEFINE_OUTPUT_LAYOUT(HAPTIC_AB),
-        DEFINE_OUTPUT_LAYOUT(MONO_HAPTIC_AB),
-        DEFINE_OUTPUT_LAYOUT(STEREO_HAPTIC_AB)
-#undef DEFINE_OUTPUT_LAYOUT
-    };
-    return pairs;
-}
-
-const detail::AudioChannelPairs& getVoiceAudioChannelPairs() {
-    static const detail::AudioChannelPairs pairs = {
-#define DEFINE_VOICE_LAYOUT(n)                                                 \
-            {                                                                  \
-                AUDIO_CHANNEL_IN_VOICE_##n,                                    \
-                AudioChannelLayout::make<AudioChannelLayout::Tag::voiceMask>(  \
-                        AudioChannelLayout::VOICE_##n)                         \
-            }
-        DEFINE_VOICE_LAYOUT(UPLINK_MONO),
-        DEFINE_VOICE_LAYOUT(DNLINK_MONO),
-        DEFINE_VOICE_LAYOUT(CALL_MONO)
-#undef DEFINE_VOICE_LAYOUT
-    };
-    return pairs;
-}
-
-AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
-        const std::string& connection = "") {
-    AudioDeviceDescription result;
-    result.type = type;
-    result.connection = connection;
-    return result;
-}
-
-void append_AudioDeviceDescription(detail::AudioDevicePairs& pairs,
-        audio_devices_t inputType, audio_devices_t outputType,
-        AudioDeviceType inType, AudioDeviceType outType,
-        const std::string& connection = "") {
-    pairs.push_back(std::make_pair(inputType, make_AudioDeviceDescription(inType, connection)));
-    pairs.push_back(std::make_pair(outputType, make_AudioDeviceDescription(outType, connection)));
-}
-
-const detail::AudioDevicePairs& getAudioDevicePairs() {
-    static const detail::AudioDevicePairs pairs = []() {
-        detail::AudioDevicePairs pairs = {{
-            {
-                AUDIO_DEVICE_NONE, AudioDeviceDescription{}
-            },
-            {
-                AUDIO_DEVICE_OUT_EARPIECE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER_EARPIECE)
-            },
-            {
-                AUDIO_DEVICE_OUT_SPEAKER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER)
-            },
-            {
-                AUDIO_DEVICE_OUT_WIRED_HEADPHONE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_HEADPHONE,
-                        AudioDeviceDescription::CONNECTION_ANALOG())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_SCO, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_DEVICE,
-                        AudioDeviceDescription::CONNECTION_BT_SCO())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_CARKIT,
-                        AudioDeviceDescription::CONNECTION_BT_SCO())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_HEADPHONE,
-                        AudioDeviceDescription::CONNECTION_BT_A2DP())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER,
-                        AudioDeviceDescription::CONNECTION_BT_A2DP())
-            },
-            {
-                AUDIO_DEVICE_OUT_TELEPHONY_TX, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_TELEPHONY_TX)
-            },
-            {
-                AUDIO_DEVICE_OUT_AUX_LINE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_LINE_AUX)
-            },
-            {
-                AUDIO_DEVICE_OUT_SPEAKER_SAFE, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER_SAFE)
-            },
-            {
-                AUDIO_DEVICE_OUT_HEARING_AID, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_HEARING_AID,
-                        AudioDeviceDescription::CONNECTION_WIRELESS())
-            },
-            {
-                AUDIO_DEVICE_OUT_ECHO_CANCELLER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_ECHO_CANCELLER)
-            },
-            {
-                AUDIO_DEVICE_OUT_BLE_SPEAKER, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_SPEAKER,
-                        AudioDeviceDescription::CONNECTION_BT_LE())
-            },
-            {
-                AUDIO_DEVICE_OUT_BLE_BROADCAST, make_AudioDeviceDescription(
-                        AudioDeviceType::OUT_BROADCAST,
-                        AudioDeviceDescription::CONNECTION_BT_LE())
-            },
-            // AUDIO_DEVICE_IN_AMBIENT and IN_COMMUNICATION are removed since they were deprecated.
-            {
-                AUDIO_DEVICE_IN_BUILTIN_MIC, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_MICROPHONE)
-            },
-            {
-                AUDIO_DEVICE_IN_BACK_MIC, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_MICROPHONE_BACK)
-            },
-            {
-                AUDIO_DEVICE_IN_TELEPHONY_RX, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_TELEPHONY_RX)
-            },
-            {
-                AUDIO_DEVICE_IN_TV_TUNER, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_TV_TUNER)
-            },
-            {
-                AUDIO_DEVICE_IN_LOOPBACK, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_LOOPBACK)
-            },
-            {
-                AUDIO_DEVICE_IN_BLUETOOTH_BLE, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_DEVICE,
-                        AudioDeviceDescription::CONNECTION_BT_LE())
-            },
-            {
-                AUDIO_DEVICE_IN_ECHO_REFERENCE, make_AudioDeviceDescription(
-                        AudioDeviceType::IN_ECHO_REFERENCE)
-            }
-        }};
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_DEFAULT, AUDIO_DEVICE_OUT_DEFAULT,
-                AudioDeviceType::IN_DEFAULT, AudioDeviceType::OUT_DEFAULT);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_WIRED_HEADSET, AUDIO_DEVICE_OUT_WIRED_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_ANALOG());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET, AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_BT_SCO());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_HDMI, AUDIO_DEVICE_OUT_HDMI,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_HDMI());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_REMOTE_SUBMIX, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
-                AudioDeviceType::IN_SUBMIX, AudioDeviceType::OUT_SUBMIX);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET, AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET,
-                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
-                AudioDeviceDescription::CONNECTION_ANALOG());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET, AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET,
-                AudioDeviceType::IN_DOCK, AudioDeviceType::OUT_DOCK,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_USB_ACCESSORY, AUDIO_DEVICE_OUT_USB_ACCESSORY,
-                AudioDeviceType::IN_ACCESSORY, AudioDeviceType::OUT_ACCESSORY,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_USB_DEVICE, AUDIO_DEVICE_OUT_USB_DEVICE,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_FM_TUNER, AUDIO_DEVICE_OUT_FM,
-                AudioDeviceType::IN_FM_TUNER, AudioDeviceType::OUT_FM);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_LINE, AUDIO_DEVICE_OUT_LINE,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_ANALOG());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_SPDIF, AUDIO_DEVICE_OUT_SPDIF,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_SPDIF());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_BT_A2DP());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_IP, AUDIO_DEVICE_OUT_IP,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_IP_V4());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_OUT_BUS,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_BUS());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_PROXY, AUDIO_DEVICE_OUT_PROXY,
-                AudioDeviceType::IN_AFE_PROXY, AudioDeviceType::OUT_AFE_PROXY);
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_USB_HEADSET, AUDIO_DEVICE_OUT_USB_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_USB());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_HDMI_ARC, AUDIO_DEVICE_OUT_HDMI_ARC,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_HDMI_ARC());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_HDMI_EARC, AUDIO_DEVICE_OUT_HDMI_EARC,
-                AudioDeviceType::IN_DEVICE, AudioDeviceType::OUT_DEVICE,
-                AudioDeviceDescription::CONNECTION_HDMI_EARC());
-        append_AudioDeviceDescription(pairs,
-                AUDIO_DEVICE_IN_BLE_HEADSET, AUDIO_DEVICE_OUT_BLE_HEADSET,
-                AudioDeviceType::IN_HEADSET, AudioDeviceType::OUT_HEADSET,
-                AudioDeviceDescription::CONNECTION_BT_LE());
-        return pairs;
-    }();
-    return pairs;
-}
-
-AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
-    AudioFormatDescription result;
-    result.type = type;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType pcm) {
-    auto result = make_AudioFormatDescription(AudioFormatType::PCM);
-    result.pcm = pcm;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(const std::string& encoding) {
-    AudioFormatDescription result;
-    result.encoding = encoding;
-    return result;
-}
-
-AudioFormatDescription make_AudioFormatDescription(PcmType transport,
-        const std::string& encoding) {
-    auto result = make_AudioFormatDescription(encoding);
-    result.pcm = transport;
-    return result;
-}
-
-const detail::AudioFormatPairs& getAudioFormatPairs() {
-    static const detail::AudioFormatPairs pairs = {{
-        {
-            AUDIO_FORMAT_INVALID,
-            make_AudioFormatDescription(AudioFormatType::SYS_RESERVED_INVALID)
-        },
-        {
-            AUDIO_FORMAT_DEFAULT, AudioFormatDescription{}
-        },
-        {
-            AUDIO_FORMAT_PCM_16_BIT, make_AudioFormatDescription(PcmType::INT_16_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_8_BIT, make_AudioFormatDescription(PcmType::UINT_8_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_32_BIT, make_AudioFormatDescription(PcmType::INT_32_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_8_24_BIT, make_AudioFormatDescription(PcmType::FIXED_Q_8_24)
-        },
-        {
-            AUDIO_FORMAT_PCM_FLOAT, make_AudioFormatDescription(PcmType::FLOAT_32_BIT)
-        },
-        {
-            AUDIO_FORMAT_PCM_24_BIT_PACKED, make_AudioFormatDescription(PcmType::INT_24_BIT)
-        },
-        {
-            AUDIO_FORMAT_MP3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG)
-        },
-        {
-            AUDIO_FORMAT_AMR_NB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_NB)
-        },
-        {
-            AUDIO_FORMAT_AMR_WB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB)
-        },
-        {
-            AUDIO_FORMAT_AAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MP4)
-        },
-        {
-            AUDIO_FORMAT_AAC_MAIN, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_MAIN)
-        },
-        {
-            AUDIO_FORMAT_AAC_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LC)
-        },
-        {
-            AUDIO_FORMAT_AAC_SSR, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SSR)
-        },
-        {
-            AUDIO_FORMAT_AAC_LTP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LTP)
-        },
-        {
-            AUDIO_FORMAT_AAC_HE_V1, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V1)
-        },
-        {
-            AUDIO_FORMAT_AAC_SCALABLE,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_SCALABLE)
-        },
-        {
-            AUDIO_FORMAT_AAC_ERLC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ERLC)
-        },
-        {
-            AUDIO_FORMAT_AAC_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LD)
-        },
-        {
-            AUDIO_FORMAT_AAC_HE_V2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_HE_V2)
-        },
-        {
-            AUDIO_FORMAT_AAC_ELD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ELD)
-        },
-        {
-            AUDIO_FORMAT_AAC_XHE, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_XHE)
-        },
-        // AUDIO_FORMAT_HE_AAC_V1 and HE_AAC_V2 are removed since they were deprecated long time
-        // ago.
-        {
-            AUDIO_FORMAT_VORBIS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_VORBIS)
-        },
-        {
-            AUDIO_FORMAT_OPUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_OPUS)
-        },
-        {
-            AUDIO_FORMAT_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC3)
-        },
-        {
-            AUDIO_FORMAT_E_AC3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3)
-        },
-        {
-            AUDIO_FORMAT_E_AC3_JOC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EAC3_JOC)
-        },
-        {
-            AUDIO_FORMAT_DTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS)
-        },
-        {
-            AUDIO_FORMAT_DTS_HD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_HD)
-        },
-        // In the future, we would like to represent encapsulated bitstreams as
-        // nested AudioFormatDescriptions. The legacy 'AUDIO_FORMAT_IEC61937' type doesn't
-        // specify the format of the encapsulated bitstream.
-        {
-            AUDIO_FORMAT_IEC61937,
-            make_AudioFormatDescription(PcmType::INT_16_BIT, MEDIA_MIMETYPE_AUDIO_IEC61937)
-        },
-        {
-            AUDIO_FORMAT_DOLBY_TRUEHD,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_TRUEHD)
-        },
-        {
-            AUDIO_FORMAT_EVRC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRC)
-        },
-        {
-            AUDIO_FORMAT_EVRCB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCB)
-        },
-        {
-            AUDIO_FORMAT_EVRCWB, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCWB)
-        },
-        {
-            AUDIO_FORMAT_EVRCNW, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_EVRCNW)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADIF, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADIF)
-        },
-        {
-            AUDIO_FORMAT_WMA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_WMA)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_WMA_PRO, make_AudioFormatDescription("audio/x-ms-wma.pro")
-        },
-        {
-            AUDIO_FORMAT_AMR_WB_PLUS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AMR_WB_PLUS)
-        },
-        {
-            AUDIO_FORMAT_MP2, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II)
-        },
-        {
-            AUDIO_FORMAT_QCELP, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_QCELP)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_DSD, make_AudioFormatDescription("audio/vnd.sony.dsd")
-        },
-        {
-            AUDIO_FORMAT_FLAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_FLAC)
-        },
-        {
-            AUDIO_FORMAT_ALAC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_ALAC)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APE, make_AudioFormatDescription("audio/x-ape")
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_MAIN,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_MAIN)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LC)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_SSR,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SSR)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_LTP,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LTP)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_HE_V1,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V1)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_SCALABLE,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_SCALABLE)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_ERLC,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ERLC)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_LD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_LD)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_HE_V2,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_HE_V2)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_ELD,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_ELD)
-        },
-        {
-            AUDIO_FORMAT_AAC_ADTS_XHE,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_ADTS_XHE)
-        },
-        {
-            // Note: not in the IANA registry. "vnd.octel.sbc" is not BT SBC.
-            AUDIO_FORMAT_SBC, make_AudioFormatDescription("audio/x-sbc")
-        },
-        {
-            AUDIO_FORMAT_APTX, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_APTX)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_HD, make_AudioFormatDescription("audio/vnd.qcom.aptx.hd")
-        },
-        {
-            AUDIO_FORMAT_AC4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AC4)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LDAC, make_AudioFormatDescription("audio/vnd.sony.ldac")
-        },
-        {
-            AUDIO_FORMAT_MAT, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_MAT_1_0,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".1.0"))
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_MAT_2_0,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.0"))
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_MAT_2_1,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DOLBY_MAT + std::string(".2.1"))
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC)
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM_LC, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_LC)
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM_HE_V1,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V1)
-        },
-        {
-            AUDIO_FORMAT_AAC_LATM_HE_V2,
-            make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_AAC_LATM_HE_V2)
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_CELT, make_AudioFormatDescription("audio/x-celt")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_ADAPTIVE, make_AudioFormatDescription("audio/vnd.qcom.aptx.adaptive")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LHDC, make_AudioFormatDescription("audio/vnd.savitech.lhdc")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LHDC_LL, make_AudioFormatDescription("audio/vnd.savitech.lhdc.ll")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_APTX_TWSP, make_AudioFormatDescription("audio/vnd.qcom.aptx.twsp")
-        },
-        {
-            // Note: not in the IANA registry.
-            AUDIO_FORMAT_LC3, make_AudioFormatDescription("audio/x-lc3")
-        },
-        {
-            AUDIO_FORMAT_MPEGH, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_BL_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L3)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_BL_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_BL_L4)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_LC_L3, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L3)
-        },
-        {
-            AUDIO_FORMAT_MPEGH_LC_L4, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_MPEGH_LC_L4)
-        },
-        {
-            AUDIO_FORMAT_IEC60958,
-            make_AudioFormatDescription(PcmType::INT_24_BIT, MEDIA_MIMETYPE_AUDIO_IEC60958)
-        },
-        {
-            AUDIO_FORMAT_DTS_UHD, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DTS_UHD)
-        },
-        {
-            AUDIO_FORMAT_DRA, make_AudioFormatDescription(MEDIA_MIMETYPE_AUDIO_DRA)
-        },
-    }};
-    return pairs;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(const std::vector<std::pair<S, T>>& v) {
-    std::unordered_map<S, T> result(v.begin(), v.end());
-    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
-    return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<S, T> make_DirectMap(
-        const std::vector<std::pair<S, T>>& v1, const std::vector<std::pair<S, T>>& v2) {
-    std::unordered_map<S, T> result(v1.begin(), v1.end());
-    LOG_ALWAYS_FATAL_IF(result.size() != v1.size(), "Duplicate key elements detected in v1");
-    result.insert(v2.begin(), v2.end());
-    LOG_ALWAYS_FATAL_IF(result.size() != v1.size() + v2.size(),
-            "Duplicate key elements detected in v1+v2");
-    return result;
-}
-
-template<typename S, typename T>
-std::unordered_map<T, S> make_ReverseMap(const std::vector<std::pair<S, T>>& v) {
-    std::unordered_map<T, S> result;
-    std::transform(v.begin(), v.end(), std::inserter(result, result.begin()),
-            [](const std::pair<S, T>& p) {
-                return std::make_pair(p.second, p.first);
-            });
-    LOG_ALWAYS_FATAL_IF(result.size() != v.size(), "Duplicate key elements detected");
-    return result;
-}
-
-}  // namespace
-
-audio_channel_mask_t aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
-        int aidlLayout, bool isInput) {
-    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
-    const int aidlLayoutInitial = aidlLayout; // for error message
-    audio_channel_mask_t legacy = AUDIO_CHANNEL_NONE;
-    for (const auto& bitPair : bitMapping) {
-        if ((aidlLayout & bitPair.second) == bitPair.second) {
-            legacy = static_cast<audio_channel_mask_t>(legacy | bitPair.first);
-            aidlLayout &= ~bitPair.second;
-            if (aidlLayout == 0) {
-                return legacy;
-            }
-        }
-    }
-    ALOGE("%s: aidl layout 0x%x contains bits 0x%x that have no match to legacy %s bits",
-            __func__, aidlLayoutInitial, aidlLayout, isInput ? "input" : "output");
-    return AUDIO_CHANNEL_NONE;
-}
-
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-        const AudioChannelLayout& aidl, bool isInput) {
-    using ReverseMap = std::unordered_map<AudioChannelLayout, audio_channel_mask_t>;
-    using Tag = AudioChannelLayout::Tag;
-    static const ReverseMap mIn = make_ReverseMap(getInAudioChannelPairs());
-    static const ReverseMap mOut = make_ReverseMap(getOutAudioChannelPairs());
-    static const ReverseMap mVoice = make_ReverseMap(getVoiceAudioChannelPairs());
-
-    auto convert = [](const AudioChannelLayout& aidl, const ReverseMap& m,
-            const char* func, const char* type) -> ConversionResult<audio_channel_mask_t> {
-        if (auto it = m.find(aidl); it != m.end()) {
-            return it->second;
-        } else {
-            ALOGW("%s: no legacy %s audio_channel_mask_t found for %s", func, type,
-                    aidl.toString().c_str());
-            return unexpected(BAD_VALUE);
-        }
-    };
-
-    switch (aidl.getTag()) {
-        case Tag::none:
-            return AUDIO_CHANNEL_NONE;
-        case Tag::invalid:
-            return AUDIO_CHANNEL_INVALID;
-        case Tag::indexMask:
-            // Index masks do not have pre-defined values.
-            if (const int bits = aidl.get<Tag::indexMask>();
-                    __builtin_popcount(bits) != 0 &&
-                    __builtin_popcount(bits) <= AUDIO_CHANNEL_COUNT_MAX) {
-                return audio_channel_mask_from_representation_and_bits(
-                        AUDIO_CHANNEL_REPRESENTATION_INDEX, bits);
-            } else {
-                ALOGE("%s: invalid indexMask value 0x%x in %s",
-                        __func__, bits, aidl.toString().c_str());
-                return unexpected(BAD_VALUE);
-            }
-        case Tag::layoutMask:
-            // The fast path is to find a direct match for some known layout mask.
-            if (const auto layoutMatch = convert(aidl, isInput ? mIn : mOut, __func__,
-                    isInput ? "input" : "output");
-                    layoutMatch.ok()) {
-                return layoutMatch;
-            }
-            // If a match for a predefined layout wasn't found, make a custom one from bits.
-            if (audio_channel_mask_t bitMask =
-                    aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
-                            aidl.get<Tag::layoutMask>(), isInput);
-                    bitMask != AUDIO_CHANNEL_NONE) {
-                return bitMask;
-            }
-            return unexpected(BAD_VALUE);
-        case Tag::voiceMask:
-            return convert(aidl, mVoice, __func__, "voice");
-    }
-    ALOGE("%s: unexpected tag value %d", __func__, aidl.getTag());
-    return unexpected(BAD_VALUE);
-}
-
-int legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
-        audio_channel_mask_t legacy, bool isInput) {
-    auto& bitMapping = isInput ? getInAudioChannelBits() : getOutAudioChannelBits();
-    const int legacyInitial = legacy; // for error message
-    int aidlLayout = 0;
-    for (const auto& bitPair : bitMapping) {
-        if ((legacy & bitPair.first) == bitPair.first) {
-            aidlLayout |= bitPair.second;
-            legacy = static_cast<audio_channel_mask_t>(legacy & ~bitPair.first);
-            if (legacy == 0) {
-                return aidlLayout;
-            }
-        }
-    }
-    ALOGE("%s: legacy %s audio_channel_mask_t 0x%x contains unrecognized bits 0x%x",
-            __func__, isInput ? "input" : "output", legacyInitial, legacy);
-    return 0;
-}
-
-ConversionResult<AudioChannelLayout> legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
-        audio_channel_mask_t legacy, bool isInput) {
-    using DirectMap = std::unordered_map<audio_channel_mask_t, AudioChannelLayout>;
-    using Tag = AudioChannelLayout::Tag;
-    static const DirectMap mInAndVoice = make_DirectMap(
-            getInAudioChannelPairs(), getVoiceAudioChannelPairs());
-    static const DirectMap mOut = make_DirectMap(getOutAudioChannelPairs());
-
-    auto convert = [](const audio_channel_mask_t legacy, const DirectMap& m,
-            const char* func, const char* type) -> ConversionResult<AudioChannelLayout> {
-        if (auto it = m.find(legacy); it != m.end()) {
-            return it->second;
-        } else {
-            ALOGW("%s: no AudioChannelLayout found for legacy %s audio_channel_mask_t value 0x%x",
-                    func, type, legacy);
-            return unexpected(BAD_VALUE);
-        }
-    };
-
-    if (legacy == AUDIO_CHANNEL_NONE) {
-        return AudioChannelLayout{};
-    } else if (legacy == AUDIO_CHANNEL_INVALID) {
-        return AudioChannelLayout::make<Tag::invalid>(0);
-    }
-
-    const audio_channel_representation_t repr = audio_channel_mask_get_representation(legacy);
-    if (repr == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
-        if (audio_channel_mask_is_valid(legacy)) {
-            const int indexMask = VALUE_OR_RETURN(
-                    convertIntegral<int>(audio_channel_mask_get_bits(legacy)));
-            return AudioChannelLayout::make<Tag::indexMask>(indexMask);
-        } else {
-            ALOGE("%s: legacy audio_channel_mask_t value 0x%x is invalid", __func__, legacy);
-            return unexpected(BAD_VALUE);
-        }
-    } else if (repr == AUDIO_CHANNEL_REPRESENTATION_POSITION) {
-        // The fast path is to find a direct match for some known layout mask.
-        if (const auto layoutMatch = convert(legacy, isInput ? mInAndVoice : mOut, __func__,
-                isInput ? "input / voice" : "output");
-                layoutMatch.ok()) {
-            return layoutMatch;
-        }
-        // If a match for a predefined layout wasn't found, make a custom one from bits,
-        // rejecting those with voice channel bits.
-        if (!isInput ||
-                (legacy & (AUDIO_CHANNEL_IN_VOICE_UPLINK | AUDIO_CHANNEL_IN_VOICE_DNLINK)) == 0) {
-            if (int bitMaskLayout =
-                    legacy2aidl_audio_channel_mask_t_bits_AudioChannelLayout_layout(
-                            legacy, isInput);
-                    bitMaskLayout != 0) {
-                return AudioChannelLayout::make<Tag::layoutMask>(bitMaskLayout);
-            }
-        } else {
-            ALOGE("%s: legacy audio_channel_mask_t value 0x%x contains voice bits",
-                    __func__, legacy);
-        }
-        return unexpected(BAD_VALUE);
-    }
-
-    ALOGE("%s: unknown representation %d in audio_channel_mask_t value 0x%x",
-            __func__, repr, legacy);
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
-        const AudioDeviceDescription& aidl) {
-    static const std::unordered_map<AudioDeviceDescription, audio_devices_t> m =
-            make_ReverseMap(getAudioDevicePairs());
-    if (auto it = m.find(aidl); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no legacy audio_devices_t found for %s", __func__, aidl.toString().c_str());
-        return unexpected(BAD_VALUE);
-    }
-}
-
-ConversionResult<AudioDeviceDescription> legacy2aidl_audio_devices_t_AudioDeviceDescription(
-        audio_devices_t legacy) {
-    static const std::unordered_map<audio_devices_t, AudioDeviceDescription> m =
-            make_DirectMap(getAudioDevicePairs());
-    if (auto it = m.find(legacy); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no AudioDeviceDescription found for legacy audio_devices_t value 0x%x",
-                __func__, legacy);
-        return unexpected(BAD_VALUE);
-    }
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
-        const AudioDevice& aidl,
-        audio_devices_t* legacyType, char* legacyAddress) {
-    *legacyType = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    return aidl2legacy_string(
-                    aidl.address.get<AudioDeviceAddress::id>(),
-                    legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN);
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
-        const AudioDevice& aidl,
-        audio_devices_t* legacyType, String8* legacyAddress) {
-    *legacyType = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    *legacyAddress = VALUE_OR_RETURN_STATUS(aidl2legacy_string_view_String8(
-                    aidl.address.get<AudioDeviceAddress::id>()));
-    return OK;
-}
-
-status_t aidl2legacy_AudioDevice_audio_device(
-        const AudioDevice& aidl,
-        audio_devices_t* legacyType, std::string* legacyAddress) {
-    *legacyType = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioDeviceDescription_audio_devices_t(aidl.type));
-    *legacyAddress = aidl.address.get<AudioDeviceAddress::id>();
-    return OK;
-}
-
-ConversionResult<AudioDevice> legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const char* legacyAddress) {
-    AudioDevice aidl;
-    aidl.type = VALUE_OR_RETURN(
-            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
-    const std::string aidl_id = VALUE_OR_RETURN(
-            legacy2aidl_string(legacyAddress, AUDIO_DEVICE_MAX_ADDRESS_LEN));
-    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
-    return aidl;
-}
-
-ConversionResult<AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const String8& legacyAddress) {
-    AudioDevice aidl;
-    aidl.type = VALUE_OR_RETURN(
-            legacy2aidl_audio_devices_t_AudioDeviceDescription(legacyType));
-    const std::string aidl_id = VALUE_OR_RETURN(
-            legacy2aidl_String8_string(legacyAddress));
-    aidl.address = AudioDeviceAddress::make<AudioDeviceAddress::id>(aidl_id);
-    return aidl;
-}
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
-        const AudioFormatDescription& aidl) {
-    static const std::unordered_map<AudioFormatDescription, audio_format_t> m =
-            make_ReverseMap(getAudioFormatPairs());
-    if (auto it = m.find(aidl); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no legacy audio_format_t found for %s", __func__, aidl.toString().c_str());
-        return unexpected(BAD_VALUE);
-    }
-}
-
-ConversionResult<AudioFormatDescription> legacy2aidl_audio_format_t_AudioFormatDescription(
-        audio_format_t legacy) {
-    static const std::unordered_map<audio_format_t, AudioFormatDescription> m =
-            make_DirectMap(getAudioFormatPairs());
-    if (auto it = m.find(legacy); it != m.end()) {
-        return it->second;
-    } else {
-        ALOGE("%s: no AudioFormatDescription found for legacy audio_format_t value 0x%x",
-                __func__, legacy);
-        return unexpected(BAD_VALUE);
-    }
-}
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_AudioGainMode_audio_gain_mode_t(
-        AudioGainMode aidl) {
+ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
+        media::AudioIoConfigEvent aidl) {
     switch (aidl) {
-        case AudioGainMode::JOINT:
-            return AUDIO_GAIN_MODE_JOINT;
-        case AudioGainMode::CHANNELS:
-            return AUDIO_GAIN_MODE_CHANNELS;
-        case AudioGainMode::RAMP:
-            return AUDIO_GAIN_MODE_RAMP;
+        case media::AudioIoConfigEvent::OUTPUT_REGISTERED:
+            return AUDIO_OUTPUT_REGISTERED;
+        case media::AudioIoConfigEvent::OUTPUT_OPENED:
+            return AUDIO_OUTPUT_OPENED;
+        case media::AudioIoConfigEvent::OUTPUT_CLOSED:
+            return AUDIO_OUTPUT_CLOSED;
+        case media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED:
+            return AUDIO_OUTPUT_CONFIG_CHANGED;
+        case media::AudioIoConfigEvent::INPUT_REGISTERED:
+            return AUDIO_INPUT_REGISTERED;
+        case media::AudioIoConfigEvent::INPUT_OPENED:
+            return AUDIO_INPUT_OPENED;
+        case media::AudioIoConfigEvent::INPUT_CLOSED:
+            return AUDIO_INPUT_CLOSED;
+        case media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED:
+            return AUDIO_INPUT_CONFIG_CHANGED;
+        case media::AudioIoConfigEvent::CLIENT_STARTED:
+            return AUDIO_CLIENT_STARTED;
     }
     return unexpected(BAD_VALUE);
 }
 
-ConversionResult<AudioGainMode> legacy2aidl_audio_gain_mode_t_AudioGainMode(
-        audio_gain_mode_t legacy) {
+ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
+        audio_io_config_event_t legacy) {
     switch (legacy) {
-        case AUDIO_GAIN_MODE_JOINT:
-            return AudioGainMode::JOINT;
-        case AUDIO_GAIN_MODE_CHANNELS:
-            return AudioGainMode::CHANNELS;
-        case AUDIO_GAIN_MODE_RAMP:
-            return AudioGainMode::RAMP;
+        case AUDIO_OUTPUT_REGISTERED:
+            return media::AudioIoConfigEvent::OUTPUT_REGISTERED;
+        case AUDIO_OUTPUT_OPENED:
+            return media::AudioIoConfigEvent::OUTPUT_OPENED;
+        case AUDIO_OUTPUT_CLOSED:
+            return media::AudioIoConfigEvent::OUTPUT_CLOSED;
+        case AUDIO_OUTPUT_CONFIG_CHANGED:
+            return media::AudioIoConfigEvent::OUTPUT_CONFIG_CHANGED;
+        case AUDIO_INPUT_REGISTERED:
+            return media::AudioIoConfigEvent::INPUT_REGISTERED;
+        case AUDIO_INPUT_OPENED:
+            return media::AudioIoConfigEvent::INPUT_OPENED;
+        case AUDIO_INPUT_CLOSED:
+            return media::AudioIoConfigEvent::INPUT_CLOSED;
+        case AUDIO_INPUT_CONFIG_CHANGED:
+            return media::AudioIoConfigEvent::INPUT_CONFIG_CHANGED;
+        case AUDIO_CLIENT_STARTED:
+            return media::AudioIoConfigEvent::CLIENT_STARTED;
     }
     return unexpected(BAD_VALUE);
 }
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl) {
-    return convertBitmask<audio_gain_mode_t, int32_t, audio_gain_mode_t, AudioGainMode>(
-            aidl, aidl2legacy_AudioGainMode_audio_gain_mode_t,
-            // AudioGainMode is index-based.
-            indexToEnum_index<AudioGainMode>,
-            // AUDIO_GAIN_MODE_* constants are mask-based.
-            enumToMask_bitmask<audio_gain_mode_t, audio_gain_mode_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy) {
-    return convertBitmask<int32_t, audio_gain_mode_t, AudioGainMode, audio_gain_mode_t>(
-            legacy, legacy2aidl_audio_gain_mode_t_AudioGainMode,
-            // AUDIO_GAIN_MODE_* constants are mask-based.
-            indexToEnum_bitmask<audio_gain_mode_t>,
-            // AudioGainMode is index-based.
-            enumToMask_index<int32_t, AudioGainMode>);
-}
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
-        const AudioGainConfig& aidl, bool isInput) {
-    audio_gain_config legacy;
-    legacy.index = VALUE_OR_RETURN(convertIntegral<int>(aidl.index));
-    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
-    legacy.channel_mask = VALUE_OR_RETURN(
-            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
-    const bool isJoint = bitmaskIsSet(aidl.mode, AudioGainMode::JOINT);
-    size_t numValues = isJoint ? 1
-                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
-                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
-    if (aidl.values.size() != numValues || aidl.values.size() > std::size(legacy.values)) {
-        return unexpected(BAD_VALUE);
-    }
-    for (size_t i = 0; i < numValues; ++i) {
-        legacy.values[i] = VALUE_OR_RETURN(convertIntegral<int>(aidl.values[i]));
-    }
-    legacy.ramp_duration_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.rampDurationMs));
-    return legacy;
-}
-
-ConversionResult<AudioGainConfig> legacy2aidl_audio_gain_config_AudioGainConfig(
-        const audio_gain_config& legacy, bool isInput) {
-    AudioGainConfig aidl;
-    aidl.index = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.index));
-    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
-    aidl.channelMask = VALUE_OR_RETURN(
-            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    const bool isJoint = (legacy.mode & AUDIO_GAIN_MODE_JOINT) != 0;
-    size_t numValues = isJoint ? 1
-                               : isInput ? audio_channel_count_from_in_mask(legacy.channel_mask)
-                                         : audio_channel_count_from_out_mask(legacy.channel_mask);
-    aidl.values.resize(numValues);
-    for (size_t i = 0; i < numValues; ++i) {
-        aidl.values[i] = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.values[i]));
-    }
-    aidl.rampDurationMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.ramp_duration_ms));
-    return aidl;
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_AudioInputFlags_audio_input_flags_t(
-        AudioInputFlags aidl) {
-    switch (aidl) {
-        case AudioInputFlags::FAST:
-            return AUDIO_INPUT_FLAG_FAST;
-        case AudioInputFlags::HW_HOTWORD:
-            return AUDIO_INPUT_FLAG_HW_HOTWORD;
-        case AudioInputFlags::RAW:
-            return AUDIO_INPUT_FLAG_RAW;
-        case AudioInputFlags::SYNC:
-            return AUDIO_INPUT_FLAG_SYNC;
-        case AudioInputFlags::MMAP_NOIRQ:
-            return AUDIO_INPUT_FLAG_MMAP_NOIRQ;
-        case AudioInputFlags::VOIP_TX:
-            return AUDIO_INPUT_FLAG_VOIP_TX;
-        case AudioInputFlags::HW_AV_SYNC:
-            return AUDIO_INPUT_FLAG_HW_AV_SYNC;
-        case AudioInputFlags::DIRECT:
-            return AUDIO_INPUT_FLAG_DIRECT;
-        case AudioInputFlags::ULTRASOUND:
-            return AUDIO_INPUT_FLAG_ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioInputFlags> legacy2aidl_audio_input_flags_t_AudioInputFlags(
-        audio_input_flags_t legacy) {
-    switch (legacy) {
-        case AUDIO_INPUT_FLAG_NONE:
-            break; // shouldn't get here. must be listed  -Werror,-Wswitch
-        case AUDIO_INPUT_FLAG_FAST:
-            return AudioInputFlags::FAST;
-        case AUDIO_INPUT_FLAG_HW_HOTWORD:
-            return AudioInputFlags::HW_HOTWORD;
-        case AUDIO_INPUT_FLAG_RAW:
-            return AudioInputFlags::RAW;
-        case AUDIO_INPUT_FLAG_SYNC:
-            return AudioInputFlags::SYNC;
-        case AUDIO_INPUT_FLAG_MMAP_NOIRQ:
-            return AudioInputFlags::MMAP_NOIRQ;
-        case AUDIO_INPUT_FLAG_VOIP_TX:
-            return AudioInputFlags::VOIP_TX;
-        case AUDIO_INPUT_FLAG_HW_AV_SYNC:
-            return AudioInputFlags::HW_AV_SYNC;
-        case AUDIO_INPUT_FLAG_DIRECT:
-            return AudioInputFlags::DIRECT;
-        case AUDIO_INPUT_FLAG_ULTRASOUND:
-            return AudioInputFlags::ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_AudioOutputFlags_audio_output_flags_t(
-        AudioOutputFlags aidl) {
-    switch (aidl) {
-        case AudioOutputFlags::DIRECT:
-            return AUDIO_OUTPUT_FLAG_DIRECT;
-        case AudioOutputFlags::PRIMARY:
-            return AUDIO_OUTPUT_FLAG_PRIMARY;
-        case AudioOutputFlags::FAST:
-            return AUDIO_OUTPUT_FLAG_FAST;
-        case AudioOutputFlags::DEEP_BUFFER:
-            return AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
-        case AudioOutputFlags::COMPRESS_OFFLOAD:
-            return AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD;
-        case AudioOutputFlags::NON_BLOCKING:
-            return AUDIO_OUTPUT_FLAG_NON_BLOCKING;
-        case AudioOutputFlags::HW_AV_SYNC:
-            return AUDIO_OUTPUT_FLAG_HW_AV_SYNC;
-        case AudioOutputFlags::TTS:
-            return AUDIO_OUTPUT_FLAG_TTS;
-        case AudioOutputFlags::RAW:
-            return AUDIO_OUTPUT_FLAG_RAW;
-        case AudioOutputFlags::SYNC:
-            return AUDIO_OUTPUT_FLAG_SYNC;
-        case AudioOutputFlags::IEC958_NONAUDIO:
-            return AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
-        case AudioOutputFlags::DIRECT_PCM:
-            return AUDIO_OUTPUT_FLAG_DIRECT_PCM;
-        case AudioOutputFlags::MMAP_NOIRQ:
-            return AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
-        case AudioOutputFlags::VOIP_RX:
-            return AUDIO_OUTPUT_FLAG_VOIP_RX;
-        case AudioOutputFlags::INCALL_MUSIC:
-            return AUDIO_OUTPUT_FLAG_INCALL_MUSIC;
-        case AudioOutputFlags::GAPLESS_OFFLOAD:
-            return AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD;
-        case AudioOutputFlags::ULTRASOUND:
-            return AUDIO_OUTPUT_FLAG_ULTRASOUND;
-        case AudioOutputFlags::SPATIALIZER:
-            return AUDIO_OUTPUT_FLAG_SPATIALIZER;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioOutputFlags> legacy2aidl_audio_output_flags_t_AudioOutputFlags(
-        audio_output_flags_t legacy) {
-    switch (legacy) {
-        case AUDIO_OUTPUT_FLAG_NONE:
-            break; // shouldn't get here. must be listed  -Werror,-Wswitch
-        case AUDIO_OUTPUT_FLAG_DIRECT:
-            return AudioOutputFlags::DIRECT;
-        case AUDIO_OUTPUT_FLAG_PRIMARY:
-            return AudioOutputFlags::PRIMARY;
-        case AUDIO_OUTPUT_FLAG_FAST:
-            return AudioOutputFlags::FAST;
-        case AUDIO_OUTPUT_FLAG_DEEP_BUFFER:
-            return AudioOutputFlags::DEEP_BUFFER;
-        case AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD:
-            return AudioOutputFlags::COMPRESS_OFFLOAD;
-        case AUDIO_OUTPUT_FLAG_NON_BLOCKING:
-            return AudioOutputFlags::NON_BLOCKING;
-        case AUDIO_OUTPUT_FLAG_HW_AV_SYNC:
-            return AudioOutputFlags::HW_AV_SYNC;
-        case AUDIO_OUTPUT_FLAG_TTS:
-            return AudioOutputFlags::TTS;
-        case AUDIO_OUTPUT_FLAG_RAW:
-            return AudioOutputFlags::RAW;
-        case AUDIO_OUTPUT_FLAG_SYNC:
-            return AudioOutputFlags::SYNC;
-        case AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO:
-            return AudioOutputFlags::IEC958_NONAUDIO;
-        case AUDIO_OUTPUT_FLAG_DIRECT_PCM:
-            return AudioOutputFlags::DIRECT_PCM;
-        case AUDIO_OUTPUT_FLAG_MMAP_NOIRQ:
-            return AudioOutputFlags::MMAP_NOIRQ;
-        case AUDIO_OUTPUT_FLAG_VOIP_RX:
-            return AudioOutputFlags::VOIP_RX;
-        case AUDIO_OUTPUT_FLAG_INCALL_MUSIC:
-            return AudioOutputFlags::INCALL_MUSIC;
-        case AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD:
-            return AudioOutputFlags::GAPLESS_OFFLOAD;
-        case AUDIO_OUTPUT_FLAG_ULTRASOUND:
-            return AudioOutputFlags::ULTRASOUND;
-        case AUDIO_OUTPUT_FLAG_SPATIALIZER:
-            return AudioOutputFlags::SPATIALIZER;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
-        int32_t aidl) {
-    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
-    LegacyMask converted = VALUE_OR_RETURN(
-            (convertBitmask<LegacyMask, int32_t, audio_input_flags_t, AudioInputFlags>(
-                    aidl, aidl2legacy_AudioInputFlags_audio_input_flags_t,
-                    indexToEnum_index<AudioInputFlags>,
-                    enumToMask_bitmask<LegacyMask, audio_input_flags_t>)));
-    return static_cast<audio_input_flags_t>(converted);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
-        audio_input_flags_t legacy) {
-    using LegacyMask = std::underlying_type_t<audio_input_flags_t>;
-
-    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
-    return convertBitmask<int32_t, LegacyMask, AudioInputFlags, audio_input_flags_t>(
-            legacyMask, legacy2aidl_audio_input_flags_t_AudioInputFlags,
-            indexToEnum_bitmask<audio_input_flags_t>,
-            enumToMask_index<int32_t, AudioInputFlags>);
-}
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
-        int32_t aidl) {
-    return convertBitmask<audio_output_flags_t,
-            int32_t,
-            audio_output_flags_t,
-            AudioOutputFlags>(
-            aidl, aidl2legacy_AudioOutputFlags_audio_output_flags_t,
-            indexToEnum_index<AudioOutputFlags>,
-            enumToMask_bitmask<audio_output_flags_t, audio_output_flags_t>);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
-        audio_output_flags_t legacy) {
-    using LegacyMask = std::underlying_type_t<audio_output_flags_t>;
-
-    LegacyMask legacyMask = static_cast<LegacyMask>(legacy);
-    return convertBitmask<int32_t, LegacyMask, AudioOutputFlags, audio_output_flags_t>(
-            legacyMask, legacy2aidl_audio_output_flags_t_AudioOutputFlags,
-            indexToEnum_bitmask<audio_output_flags_t>,
-            enumToMask_index<int32_t, AudioOutputFlags>);
-}
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const AudioIoFlags& aidl, bool isInput) {
-    audio_io_flags legacy;
-    if (isInput) {
-        legacy.input = VALUE_OR_RETURN(
-                aidl2legacy_int32_t_audio_input_flags_t_mask(
-                        VALUE_OR_RETURN(UNION_GET(aidl, input))));
-    } else {
-        legacy.output = VALUE_OR_RETURN(
-                aidl2legacy_int32_t_audio_output_flags_t_mask(
-                        VALUE_OR_RETURN(UNION_GET(aidl, output))));
-    }
-    return legacy;
-}
-
-ConversionResult<AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
-        const audio_io_flags& legacy, bool isInput) {
-    AudioIoFlags aidl;
-    if (isInput) {
-        UNION_SET(aidl, input,
-                VALUE_OR_RETURN(legacy2aidl_audio_input_flags_t_int32_t_mask(legacy.input)));
-    } else {
-        UNION_SET(aidl, output,
-                VALUE_OR_RETURN(legacy2aidl_audio_output_flags_t_int32_t_mask(legacy.output)));
-    }
-    return aidl;
-}
-
-ConversionResult<audio_port_config_device_ext>
-aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
-        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
-    audio_port_config_device_ext legacy;
-    legacy.hw_module = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
-    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
-                    aidl.device, &legacy.type, legacy.address));
-    return legacy;
-}
-
-status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
-        const audio_port_config_device_ext& legacy,
-        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
-    aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    aidl->device = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
-    return OK;
-}
-
-ConversionResult<audio_stream_type_t> aidl2legacy_AudioStreamType_audio_stream_type_t(
-        AudioStreamType aidl) {
-    switch (aidl) {
-        case AudioStreamType::INVALID:
-            break;  // return error
-        case AudioStreamType::SYS_RESERVED_DEFAULT:
-            return AUDIO_STREAM_DEFAULT;
-        case AudioStreamType::VOICE_CALL:
-            return AUDIO_STREAM_VOICE_CALL;
-        case AudioStreamType::SYSTEM:
-            return AUDIO_STREAM_SYSTEM;
-        case AudioStreamType::RING:
-            return AUDIO_STREAM_RING;
-        case AudioStreamType::MUSIC:
-            return AUDIO_STREAM_MUSIC;
-        case AudioStreamType::ALARM:
-            return AUDIO_STREAM_ALARM;
-        case AudioStreamType::NOTIFICATION:
-            return AUDIO_STREAM_NOTIFICATION;
-        case AudioStreamType::BLUETOOTH_SCO:
-            return AUDIO_STREAM_BLUETOOTH_SCO;
-        case AudioStreamType::ENFORCED_AUDIBLE:
-            return AUDIO_STREAM_ENFORCED_AUDIBLE;
-        case AudioStreamType::DTMF:
-            return AUDIO_STREAM_DTMF;
-        case AudioStreamType::TTS:
-            return AUDIO_STREAM_TTS;
-        case AudioStreamType::ACCESSIBILITY:
-            return AUDIO_STREAM_ACCESSIBILITY;
-        case AudioStreamType::ASSISTANT:
-            return AUDIO_STREAM_ASSISTANT;
-        case AudioStreamType::SYS_RESERVED_REROUTING:
-            return AUDIO_STREAM_REROUTING;
-        case AudioStreamType::SYS_RESERVED_PATCH:
-            return AUDIO_STREAM_PATCH;
-        case AudioStreamType::CALL_ASSISTANT:
-            return AUDIO_STREAM_CALL_ASSISTANT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStreamType> legacy2aidl_audio_stream_type_t_AudioStreamType(
-        audio_stream_type_t legacy) {
-    switch (legacy) {
-        case AUDIO_STREAM_DEFAULT:
-            return AudioStreamType::SYS_RESERVED_DEFAULT;
-        case AUDIO_STREAM_VOICE_CALL:
-            return AudioStreamType::VOICE_CALL;
-        case AUDIO_STREAM_SYSTEM:
-            return AudioStreamType::SYSTEM;
-        case AUDIO_STREAM_RING:
-            return AudioStreamType::RING;
-        case AUDIO_STREAM_MUSIC:
-            return AudioStreamType::MUSIC;
-        case AUDIO_STREAM_ALARM:
-            return AudioStreamType::ALARM;
-        case AUDIO_STREAM_NOTIFICATION:
-            return AudioStreamType::NOTIFICATION;
-        case AUDIO_STREAM_BLUETOOTH_SCO:
-            return AudioStreamType::BLUETOOTH_SCO;
-        case AUDIO_STREAM_ENFORCED_AUDIBLE:
-            return AudioStreamType::ENFORCED_AUDIBLE;
-        case AUDIO_STREAM_DTMF:
-            return AudioStreamType::DTMF;
-        case AUDIO_STREAM_TTS:
-            return AudioStreamType::TTS;
-        case AUDIO_STREAM_ACCESSIBILITY:
-            return AudioStreamType::ACCESSIBILITY;
-        case AUDIO_STREAM_ASSISTANT:
-            return AudioStreamType::ASSISTANT;
-        case AUDIO_STREAM_REROUTING:
-            return AudioStreamType::SYS_RESERVED_REROUTING;
-        case AUDIO_STREAM_PATCH:
-            return AudioStreamType::SYS_RESERVED_PATCH;
-        case AUDIO_STREAM_CALL_ASSISTANT:
-            return AudioStreamType::CALL_ASSISTANT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
-        AudioSource aidl) {
-    switch (aidl) {
-        case AudioSource::SYS_RESERVED_INVALID:
-            return AUDIO_SOURCE_INVALID;
-        case AudioSource::DEFAULT:
-            return AUDIO_SOURCE_DEFAULT;
-        case AudioSource::MIC:
-            return AUDIO_SOURCE_MIC;
-        case AudioSource::VOICE_UPLINK:
-            return AUDIO_SOURCE_VOICE_UPLINK;
-        case AudioSource::VOICE_DOWNLINK:
-            return AUDIO_SOURCE_VOICE_DOWNLINK;
-        case AudioSource::VOICE_CALL:
-            return AUDIO_SOURCE_VOICE_CALL;
-        case AudioSource::CAMCORDER:
-            return AUDIO_SOURCE_CAMCORDER;
-        case AudioSource::VOICE_RECOGNITION:
-            return AUDIO_SOURCE_VOICE_RECOGNITION;
-        case AudioSource::VOICE_COMMUNICATION:
-            return AUDIO_SOURCE_VOICE_COMMUNICATION;
-        case AudioSource::REMOTE_SUBMIX:
-            return AUDIO_SOURCE_REMOTE_SUBMIX;
-        case AudioSource::UNPROCESSED:
-            return AUDIO_SOURCE_UNPROCESSED;
-        case AudioSource::VOICE_PERFORMANCE:
-            return AUDIO_SOURCE_VOICE_PERFORMANCE;
-        case AudioSource::ULTRASOUND:
-            return AUDIO_SOURCE_ULTRASOUND;
-        case AudioSource::ECHO_REFERENCE:
-            return AUDIO_SOURCE_ECHO_REFERENCE;
-        case AudioSource::FM_TUNER:
-            return AUDIO_SOURCE_FM_TUNER;
-        case AudioSource::HOTWORD:
-            return AUDIO_SOURCE_HOTWORD;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioSource> legacy2aidl_audio_source_t_AudioSource(
-        audio_source_t legacy) {
-    switch (legacy) {
-        case AUDIO_SOURCE_INVALID:
-            return AudioSource::SYS_RESERVED_INVALID;
-        case AUDIO_SOURCE_DEFAULT:
-            return AudioSource::DEFAULT;
-        case AUDIO_SOURCE_MIC:
-            return AudioSource::MIC;
-        case AUDIO_SOURCE_VOICE_UPLINK:
-            return AudioSource::VOICE_UPLINK;
-        case AUDIO_SOURCE_VOICE_DOWNLINK:
-            return AudioSource::VOICE_DOWNLINK;
-        case AUDIO_SOURCE_VOICE_CALL:
-            return AudioSource::VOICE_CALL;
-        case AUDIO_SOURCE_CAMCORDER:
-            return AudioSource::CAMCORDER;
-        case AUDIO_SOURCE_VOICE_RECOGNITION:
-            return AudioSource::VOICE_RECOGNITION;
-        case AUDIO_SOURCE_VOICE_COMMUNICATION:
-            return AudioSource::VOICE_COMMUNICATION;
-        case AUDIO_SOURCE_REMOTE_SUBMIX:
-            return AudioSource::REMOTE_SUBMIX;
-        case AUDIO_SOURCE_UNPROCESSED:
-            return AudioSource::UNPROCESSED;
-        case AUDIO_SOURCE_VOICE_PERFORMANCE:
-            return AudioSource::VOICE_PERFORMANCE;
-        case AUDIO_SOURCE_ULTRASOUND:
-            return AudioSource::ULTRASOUND;
-        case AUDIO_SOURCE_ECHO_REFERENCE:
-            return AudioSource::ECHO_REFERENCE;
-        case AUDIO_SOURCE_FM_TUNER:
-            return AudioSource::FM_TUNER;
-        case AUDIO_SOURCE_HOTWORD:
-            return AudioSource::HOTWORD;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl) {
-    return convertReinterpret<audio_session_t>(aidl);
-}
-
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-// This type is unnamed in the original definition, thus we name it here.
-using audio_port_config_mix_ext_usecase = decltype(audio_port_config_mix_ext::usecase);
-
 ConversionResult<audio_port_config_mix_ext_usecase> aidl2legacy_AudioPortMixExtUseCase(
         const AudioPortMixExtUseCase& aidl, media::AudioPortRole role) {
-    audio_port_config_mix_ext_usecase legacy;
-
     switch (role) {
-        case media::AudioPortRole::NONE:
+        case media::AudioPortRole::NONE: {
+            audio_port_config_mix_ext_usecase legacy;
             // Just verify that the union is empty.
             VALUE_OR_RETURN(UNION_GET(aidl, unspecified));
             return legacy;
-
+        }
         case media::AudioPortRole::SOURCE:
-            // This is not a bug. A SOURCE role corresponds to the stream field.
-            legacy.stream = VALUE_OR_RETURN(aidl2legacy_AudioStreamType_audio_stream_type_t(
-                    VALUE_OR_RETURN(UNION_GET(aidl, stream))));
-            return legacy;
-
+            return aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+                    aidl, false /*isInput*/);
         case media::AudioPortRole::SINK:
-            // This is not a bug. A SINK role corresponds to the source field.
-            legacy.source = VALUE_OR_RETURN(aidl2legacy_AudioSource_audio_source_t(
-                    VALUE_OR_RETURN(UNION_GET(aidl, source))));
-            return legacy;
+            return aidl2legacy_AudioPortMixExtUseCase_audio_port_config_mix_ext_usecase(
+                    aidl, true /*isInput*/);
     }
     LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
 ConversionResult<AudioPortMixExtUseCase> legacy2aidl_AudioPortMixExtUseCase(
         const audio_port_config_mix_ext_usecase& legacy, audio_port_role_t role) {
-    AudioPortMixExtUseCase aidl;
-
     switch (role) {
-        case AUDIO_PORT_ROLE_NONE:
+        case AUDIO_PORT_ROLE_NONE: {
+            AudioPortMixExtUseCase aidl;
             UNION_SET(aidl, unspecified, false);
             return aidl;
+        }
         case AUDIO_PORT_ROLE_SOURCE:
-            // This is not a bug. A SOURCE role corresponds to the stream field.
-            UNION_SET(aidl, stream, VALUE_OR_RETURN(
-                    legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream)));
-            return aidl;
+            return legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+                    legacy, false /*isInput*/);
         case AUDIO_PORT_ROLE_SINK:
-            // This is not a bug. A SINK role corresponds to the source field.
-            UNION_SET(aidl, source,
-                      VALUE_OR_RETURN(legacy2aidl_audio_source_t_AudioSource(legacy.source)));
-            return aidl;
+            return legacy2aidl_audio_port_config_mix_ext_usecase_AudioPortMixExtUseCase(
+                    legacy, true /*isInput*/);
     }
     LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
@@ -1873,6 +220,8 @@
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
         const AudioPortMixExt& aidl, media::AudioPortRole role,
         const media::AudioPortMixExtSys& aidlMixExt) {
+    // Not using HAL-level 'aidl2legacy_AudioPortMixExt' as it does not support
+    // 'media::AudioPortRole::NONE'.
     audio_port_config_mix_ext legacy;
     legacy.hw_module = VALUE_OR_RETURN(
             aidl2legacy_int32_t_audio_module_handle_t(aidlMixExt.hwModule));
@@ -1884,6 +233,8 @@
 status_t legacy2aidl_AudioPortMixExt(
         const audio_port_config_mix_ext& legacy, audio_port_role_t role,
         AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+    // Not using HAL-level 'legacy2aidl_AudioPortMixExt' as it does not support
+    // 'AUDIO_PORT_ROLE_NONE'.
     aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
     aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
@@ -1905,12 +256,34 @@
     return legacy2aidl_audio_session_t_int32_t(legacy.session);
 }
 
+ConversionResult<audio_port_config_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
+        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlDeviceExt) {
+    audio_port_config_device_ext legacy = VALUE_OR_RETURN(
+            aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(aidl));
+    legacy.hw_module = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_module_handle_t(aidlDeviceExt.hwModule));
+    return legacy;
+}
+
+status_t legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(
+        const audio_port_config_device_ext& legacy,
+        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+    *aidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_config_device_ext_AudioPortDeviceExt(legacy));
+    aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+    return OK;
+}
+
 // This type is unnamed in the original definition, thus we name it here.
 using audio_port_config_ext = decltype(audio_port_config::ext);
 
 ConversionResult<audio_port_config_ext> aidl2legacy_AudioPortExt_audio_port_config_ext(
         const AudioPortExt& aidl, media::AudioPortType type,
         media::AudioPortRole role, const media::AudioPortExtSys& aidlSys) {
+    // Not using HAL-level 'aidl2legacy_AudioPortExt_audio_port_config_ext' as it does not support
+    // 'media::AudioPortType::SESSION'.
     audio_port_config_ext legacy;
     switch (type) {
         case media::AudioPortType::NONE:
@@ -1932,7 +305,7 @@
         case media::AudioPortType::SESSION:
             legacy.session = VALUE_OR_RETURN(
                     aidl2legacy_int32_t_audio_port_config_session_ext(
-                            VALUE_OR_RETURN(UNION_GET(aidl, session))));
+                            VALUE_OR_RETURN(UNION_GET(aidlSys, session))));
             return legacy;
 
     }
@@ -1942,6 +315,8 @@
 status_t legacy2aidl_AudioPortExt(
         const audio_port_config_ext& legacy, audio_port_type_t type, audio_port_role_t role,
         AudioPortExt* aidl, media::AudioPortExtSys* aidlSys) {
+    // Not using HAL-level 'aidl2legacy_AudioPortExt_audio_port_config_ext' as it does not support
+    // 'AUDIO_PORT_TYPE_SESSION'.
     switch (type) {
         case AUDIO_PORT_TYPE_NONE:
             UNION_SET(*aidl, unspecified, false);
@@ -1966,91 +341,47 @@
             return OK;
         }
         case AUDIO_PORT_TYPE_SESSION:
-            UNION_SET(*aidl, session, VALUE_OR_RETURN_STATUS(
+            UNION_SET(*aidl, unspecified, false);
+            UNION_SET(*aidlSys, session, VALUE_OR_RETURN_STATUS(
                             legacy2aidl_audio_port_config_session_ext_int32_t(legacy.session)));
-            UNION_SET(*aidlSys, unspecified, false);
             return OK;
     }
     LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
-ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
-        const media::AudioPortConfig& aidl) {
-    audio_port_config legacy{};
-    legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.hal.id));
+ConversionResult<audio_port_config> aidl2legacy_AudioPortConfigFw_audio_port_config(
+        const media::AudioPortConfigFw& aidl, int32_t* aidlPortId) {
+    const bool isInput = VALUE_OR_RETURN(
+            portDirection(aidl.sys.role, aidl.sys.type)) == AudioPortDirection::INPUT;
+    audio_port_config legacy;
+    int32_t aidlPortIdHolder;
+    RETURN_IF_ERROR(aidl2legacy_AudioPortConfig_audio_port_config(
+                    aidl.hal, isInput, &legacy, &aidlPortIdHolder));
+    if (aidlPortId != nullptr) *aidlPortId = aidlPortIdHolder;
     legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.sys.role));
     legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.sys.type));
-    const bool isInput =
-            VALUE_OR_RETURN(direction(aidl.sys.role, aidl.sys.type)) == Direction::INPUT;
-    if (aidl.hal.sampleRate.has_value()) {
-        legacy.sample_rate = VALUE_OR_RETURN(
-                convertIntegral<unsigned int>(aidl.hal.sampleRate.value().value));
-        legacy.config_mask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
-    }
-    if (aidl.hal.channelMask.has_value()) {
-        legacy.channel_mask =
-                VALUE_OR_RETURN(
-                        aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-                                aidl.hal.channelMask.value(), isInput));
-        legacy.config_mask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
-    }
-    if (aidl.hal.format.has_value()) {
-        legacy.format = VALUE_OR_RETURN(
-                aidl2legacy_AudioFormatDescription_audio_format_t(aidl.hal.format.value()));
-        legacy.config_mask |= AUDIO_PORT_CONFIG_FORMAT;
-    }
-    if (aidl.hal.gain.has_value()) {
-        legacy.gain = VALUE_OR_RETURN(aidl2legacy_AudioGainConfig_audio_gain_config(
-                        aidl.hal.gain.value(), isInput));
-        legacy.config_mask |= AUDIO_PORT_CONFIG_GAIN;
-    }
-    if (aidl.hal.flags.has_value()) {
-        legacy.flags = VALUE_OR_RETURN(
-                aidl2legacy_AudioIoFlags_audio_io_flags(aidl.hal.flags.value(), isInput));
-        legacy.config_mask |= AUDIO_PORT_CONFIG_FLAGS;
-    }
     legacy.ext = VALUE_OR_RETURN(
             aidl2legacy_AudioPortExt_audio_port_config_ext(
                     aidl.hal.ext, aidl.sys.type, aidl.sys.role, aidl.sys.ext));
     return legacy;
 }
 
-ConversionResult<media::AudioPortConfig> legacy2aidl_audio_port_config_AudioPortConfig(
-        const audio_port_config& legacy) {
-    media::AudioPortConfig aidl;
-    aidl.hal.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ConversionResult<media::AudioPortConfigFw> legacy2aidl_audio_port_config_AudioPortConfigFw(
+        const audio_port_config& legacy, int32_t portId) {
+    const bool isInput = VALUE_OR_RETURN(
+            portDirection(legacy.role, legacy.type)) == AudioPortDirection::INPUT;
+    media::AudioPortConfigFw aidl;
+    aidl.hal = VALUE_OR_RETURN(
+            legacy2aidl_audio_port_config_AudioPortConfig(legacy, isInput, portId));
     aidl.sys.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
     aidl.sys.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
-    const bool isInput = VALUE_OR_RETURN(
-            direction(legacy.role, legacy.type)) == Direction::INPUT;
-    if (legacy.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
-        Int aidl_sampleRate;
-        aidl_sampleRate.value = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
-        aidl.hal.sampleRate = aidl_sampleRate;
-    }
-    if (legacy.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
-        aidl.hal.channelMask = VALUE_OR_RETURN(
-                legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    }
-    if (legacy.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
-        aidl.hal.format = VALUE_OR_RETURN(
-                legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-    }
-    if (legacy.config_mask & AUDIO_PORT_CONFIG_GAIN) {
-        aidl.hal.gain = VALUE_OR_RETURN(
-                legacy2aidl_audio_gain_config_AudioGainConfig(legacy.gain, isInput));
-    }
-    if (legacy.config_mask & AUDIO_PORT_CONFIG_FLAGS) {
-        aidl.hal.flags = VALUE_OR_RETURN(
-                legacy2aidl_audio_io_flags_AudioIoFlags(legacy.flags, isInput));
-    }
     RETURN_IF_ERROR(legacy2aidl_AudioPortExt(legacy.ext, legacy.type, legacy.role,
                     &aidl.hal.ext, &aidl.sys.ext));
     return aidl;
 }
 
-ConversionResult<struct audio_patch> aidl2legacy_AudioPatch_audio_patch(
-        const media::AudioPatch& aidl) {
+ConversionResult<struct audio_patch> aidl2legacy_AudioPatchFw_audio_patch(
+        const media::AudioPatchFw& aidl) {
     struct audio_patch legacy;
     legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_patch_handle_t(aidl.id));
     legacy.num_sinks = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.sinks.size()));
@@ -2059,7 +390,7 @@
     }
     for (size_t i = 0; i < legacy.num_sinks; ++i) {
         legacy.sinks[i] =
-                VALUE_OR_RETURN(aidl2legacy_AudioPortConfig_audio_port_config(aidl.sinks[i]));
+                VALUE_OR_RETURN(aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sinks[i]));
     }
     legacy.num_sources = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.sources.size()));
     if (legacy.num_sources > AUDIO_PATCH_PORTS_MAX) {
@@ -2067,14 +398,14 @@
     }
     for (size_t i = 0; i < legacy.num_sources; ++i) {
         legacy.sources[i] =
-                VALUE_OR_RETURN(aidl2legacy_AudioPortConfig_audio_port_config(aidl.sources[i]));
+                VALUE_OR_RETURN(aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sources[i]));
     }
     return legacy;
 }
 
-ConversionResult<media::AudioPatch> legacy2aidl_audio_patch_AudioPatch(
+ConversionResult<media::AudioPatchFw> legacy2aidl_audio_patch_AudioPatchFw(
         const struct audio_patch& legacy) {
-    media::AudioPatch aidl;
+    media::AudioPatchFw aidl;
     aidl.id = VALUE_OR_RETURN(legacy2aidl_audio_patch_handle_t_int32_t(legacy.id));
 
     if (legacy.num_sinks > AUDIO_PATCH_PORTS_MAX) {
@@ -2082,14 +413,14 @@
     }
     for (unsigned int i = 0; i < legacy.num_sinks; ++i) {
         aidl.sinks.push_back(
-                VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(legacy.sinks[i])));
+                VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.sinks[i])));
     }
     if (legacy.num_sources > AUDIO_PATCH_PORTS_MAX) {
         return unexpected(BAD_VALUE);
     }
     for (unsigned int i = 0; i < legacy.num_sources; ++i) {
         aidl.sources.push_back(
-                VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfig(legacy.sources[i])));
+                VALUE_OR_RETURN(legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.sources[i])));
     }
     return aidl;
 }
@@ -2099,7 +430,7 @@
     const audio_io_handle_t io_handle = VALUE_OR_RETURN(
             aidl2legacy_int32_t_audio_io_handle_t(aidl.ioHandle));
     const struct audio_patch patch = VALUE_OR_RETURN(
-            aidl2legacy_AudioPatch_audio_patch(aidl.patch));
+            aidl2legacy_AudioPatchFw_audio_patch(aidl.patch));
     const bool isInput = aidl.isInput;
     const uint32_t sampling_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.samplingRate));
     const audio_format_t format = VALUE_OR_RETURN(
@@ -2119,7 +450,7 @@
         const sp<AudioIoDescriptor>& legacy) {
     media::AudioIoDescriptor aidl;
     aidl.ioHandle = VALUE_OR_RETURN(legacy2aidl_audio_io_handle_t_int32_t(legacy->getIoHandle()));
-    aidl.patch = VALUE_OR_RETURN(legacy2aidl_audio_patch_AudioPatch(legacy->getPatch()));
+    aidl.patch = VALUE_OR_RETURN(legacy2aidl_audio_patch_AudioPatchFw(legacy->getPatch()));
     aidl.isInput = legacy->getIsInput();
     aidl.samplingRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy->getSamplingRate()));
     aidl.format = VALUE_OR_RETURN(
@@ -2149,148 +480,6 @@
     return aidl;
 }
 
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(AudioContentType aidl) {
-    switch (aidl) {
-        case AudioContentType::UNKNOWN:
-            return AUDIO_CONTENT_TYPE_UNKNOWN;
-        case AudioContentType::SPEECH:
-            return AUDIO_CONTENT_TYPE_SPEECH;
-        case AudioContentType::MUSIC:
-            return AUDIO_CONTENT_TYPE_MUSIC;
-        case AudioContentType::MOVIE:
-            return AUDIO_CONTENT_TYPE_MOVIE;
-        case AudioContentType::SONIFICATION:
-            return AUDIO_CONTENT_TYPE_SONIFICATION;
-        case AudioContentType::ULTRASOUND:
-            return AUDIO_CONTENT_TYPE_ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy) {
-    switch (legacy) {
-        case AUDIO_CONTENT_TYPE_UNKNOWN:
-            return AudioContentType::UNKNOWN;
-        case AUDIO_CONTENT_TYPE_SPEECH:
-            return AudioContentType::SPEECH;
-        case AUDIO_CONTENT_TYPE_MUSIC:
-            return AudioContentType::MUSIC;
-        case AUDIO_CONTENT_TYPE_MOVIE:
-            return AudioContentType::MOVIE;
-        case AUDIO_CONTENT_TYPE_SONIFICATION:
-            return AudioContentType::SONIFICATION;
-        case AUDIO_CONTENT_TYPE_ULTRASOUND:
-            return AudioContentType::ULTRASOUND;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(AudioUsage aidl) {
-    switch (aidl) {
-        case AudioUsage::INVALID:
-            break;  // return error
-        case AudioUsage::UNKNOWN:
-            return AUDIO_USAGE_UNKNOWN;
-        case AudioUsage::MEDIA:
-            return AUDIO_USAGE_MEDIA;
-        case AudioUsage::VOICE_COMMUNICATION:
-            return AUDIO_USAGE_VOICE_COMMUNICATION;
-        case AudioUsage::VOICE_COMMUNICATION_SIGNALLING:
-            return AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
-        case AudioUsage::ALARM:
-            return AUDIO_USAGE_ALARM;
-        case AudioUsage::NOTIFICATION:
-            return AUDIO_USAGE_NOTIFICATION;
-        case AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE:
-            return AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
-        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST:
-            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
-        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT:
-            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT;
-        case AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED:
-            return AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED;
-        case AudioUsage::NOTIFICATION_EVENT:
-            return AUDIO_USAGE_NOTIFICATION_EVENT;
-        case AudioUsage::ASSISTANCE_ACCESSIBILITY:
-            return AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
-        case AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE:
-            return AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE;
-        case AudioUsage::ASSISTANCE_SONIFICATION:
-            return AUDIO_USAGE_ASSISTANCE_SONIFICATION;
-        case AudioUsage::GAME:
-            return AUDIO_USAGE_GAME;
-        case AudioUsage::VIRTUAL_SOURCE:
-            return AUDIO_USAGE_VIRTUAL_SOURCE;
-        case AudioUsage::ASSISTANT:
-            return AUDIO_USAGE_ASSISTANT;
-        case AudioUsage::CALL_ASSISTANT:
-            return AUDIO_USAGE_CALL_ASSISTANT;
-        case AudioUsage::EMERGENCY:
-            return AUDIO_USAGE_EMERGENCY;
-        case AudioUsage::SAFETY:
-            return AUDIO_USAGE_SAFETY;
-        case AudioUsage::VEHICLE_STATUS:
-            return AUDIO_USAGE_VEHICLE_STATUS;
-        case AudioUsage::ANNOUNCEMENT:
-            return AUDIO_USAGE_ANNOUNCEMENT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy) {
-    switch (legacy) {
-        case AUDIO_USAGE_UNKNOWN:
-            return AudioUsage::UNKNOWN;
-        case AUDIO_USAGE_MEDIA:
-            return AudioUsage::MEDIA;
-        case AUDIO_USAGE_VOICE_COMMUNICATION:
-            return AudioUsage::VOICE_COMMUNICATION;
-        case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
-            return AudioUsage::VOICE_COMMUNICATION_SIGNALLING;
-        case AUDIO_USAGE_ALARM:
-            return AudioUsage::ALARM;
-        case AUDIO_USAGE_NOTIFICATION:
-            return AudioUsage::NOTIFICATION;
-        case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
-            return AudioUsage::NOTIFICATION_TELEPHONY_RINGTONE;
-        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_REQUEST;
-        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
-            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_INSTANT;
-        case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
-            return AudioUsage::SYS_RESERVED_NOTIFICATION_COMMUNICATION_DELAYED;
-        case AUDIO_USAGE_NOTIFICATION_EVENT:
-            return AudioUsage::NOTIFICATION_EVENT;
-        case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
-            return AudioUsage::ASSISTANCE_ACCESSIBILITY;
-        case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
-            return AudioUsage::ASSISTANCE_NAVIGATION_GUIDANCE;
-        case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
-            return AudioUsage::ASSISTANCE_SONIFICATION;
-        case AUDIO_USAGE_GAME:
-            return AudioUsage::GAME;
-        case AUDIO_USAGE_VIRTUAL_SOURCE:
-            return AudioUsage::VIRTUAL_SOURCE;
-        case AUDIO_USAGE_ASSISTANT:
-            return AudioUsage::ASSISTANT;
-        case AUDIO_USAGE_CALL_ASSISTANT:
-            return AudioUsage::CALL_ASSISTANT;
-        case AUDIO_USAGE_EMERGENCY:
-            return AudioUsage::EMERGENCY;
-        case AUDIO_USAGE_SAFETY:
-            return AudioUsage::SAFETY;
-        case AUDIO_USAGE_VEHICLE_STATUS:
-            return AudioUsage::VEHICLE_STATUS;
-        case AUDIO_USAGE_ANNOUNCEMENT:
-            return AudioUsage::ANNOUNCEMENT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<audio_flags_mask_t>
 aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl) {
     switch (aidl) {
@@ -2414,140 +603,6 @@
     return aidl;
 }
 
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(AudioEncapsulationMode aidl) {
-    switch (aidl) {
-        case AudioEncapsulationMode::INVALID:
-            break;  // return error
-        case AudioEncapsulationMode::NONE:
-            return AUDIO_ENCAPSULATION_MODE_NONE;
-        case AudioEncapsulationMode::ELEMENTARY_STREAM:
-            return AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM;
-        case AudioEncapsulationMode::HANDLE:
-            return AUDIO_ENCAPSULATION_MODE_HANDLE;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_ENCAPSULATION_MODE_NONE:
-            return AudioEncapsulationMode::NONE;
-        case AUDIO_ENCAPSULATION_MODE_ELEMENTARY_STREAM:
-            return AudioEncapsulationMode::ELEMENTARY_STREAM;
-        case AUDIO_ENCAPSULATION_MODE_HANDLE:
-            return AudioEncapsulationMode::HANDLE;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(const AudioOffloadInfo& aidl) {
-    audio_offload_info_t legacy = AUDIO_INFO_INITIALIZER;
-    audio_config_base_t base = VALUE_OR_RETURN(
-            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, false /*isInput*/));
-    legacy.sample_rate = base.sample_rate;
-    legacy.channel_mask = base.channel_mask;
-    legacy.format = base.format;
-    legacy.stream_type = VALUE_OR_RETURN(
-            aidl2legacy_AudioStreamType_audio_stream_type_t(aidl.streamType));
-    legacy.bit_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitRatePerSecond));
-    legacy.duration_us = VALUE_OR_RETURN(convertIntegral<int64_t>(aidl.durationUs));
-    legacy.has_video = aidl.hasVideo;
-    legacy.is_streaming = aidl.isStreaming;
-    legacy.bit_width = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.bitWidth));
-    legacy.offload_buffer_size = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.offloadBufferSize));
-    legacy.usage = VALUE_OR_RETURN(aidl2legacy_AudioUsage_audio_usage_t(aidl.usage));
-    legacy.encapsulation_mode = VALUE_OR_RETURN(
-            aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(aidl.encapsulationMode));
-    legacy.content_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.contentId));
-    legacy.sync_id = VALUE_OR_RETURN(convertReinterpret<int32_t>(aidl.syncId));
-    return legacy;
-}
-
-ConversionResult<AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy) {
-    AudioOffloadInfo aidl;
-    // Version 0.1 fields.
-    if (legacy.size < offsetof(audio_offload_info_t, usage) + sizeof(audio_offload_info_t::usage)) {
-        return unexpected(BAD_VALUE);
-    }
-    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
-        .channel_mask = legacy.channel_mask, .format = legacy.format };
-    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(
-                    base, false /*isInput*/));
-    aidl.streamType = VALUE_OR_RETURN(
-            legacy2aidl_audio_stream_type_t_AudioStreamType(legacy.stream_type));
-    aidl.bitRatePerSecond = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_rate));
-    aidl.durationUs = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.duration_us));
-    aidl.hasVideo = legacy.has_video;
-    aidl.isStreaming = legacy.is_streaming;
-    aidl.bitWidth = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.bit_width));
-    aidl.offloadBufferSize = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.offload_buffer_size));
-    aidl.usage = VALUE_OR_RETURN(legacy2aidl_audio_usage_t_AudioUsage(legacy.usage));
-
-    // Version 0.2 fields.
-    if (legacy.version >= AUDIO_OFFLOAD_INFO_VERSION_0_2) {
-        if (legacy.size <
-            offsetof(audio_offload_info_t, sync_id) + sizeof(audio_offload_info_t::sync_id)) {
-            return unexpected(BAD_VALUE);
-        }
-        aidl.encapsulationMode = VALUE_OR_RETURN(
-                legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(
-                        legacy.encapsulation_mode));
-        aidl.contentId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.content_id));
-        aidl.syncId = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.sync_id));
-    }
-    return aidl;
-}
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const AudioConfig& aidl, bool isInput) {
-    const audio_config_base_t legacyBase = VALUE_OR_RETURN(
-            aidl2legacy_AudioConfigBase_audio_config_base_t(aidl.base, isInput));
-    audio_config_t legacy = AUDIO_CONFIG_INITIALIZER;
-    legacy.sample_rate = legacyBase.sample_rate;
-    legacy.channel_mask = legacyBase.channel_mask;
-    legacy.format = legacyBase.format;
-    legacy.offload_info = VALUE_OR_RETURN(
-            aidl2legacy_AudioOffloadInfo_audio_offload_info_t(aidl.offloadInfo));
-    legacy.frame_count = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.frameCount));
-    return legacy;
-}
-
-ConversionResult<AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput) {
-    const audio_config_base_t base = { .sample_rate = legacy.sample_rate,
-        .channel_mask = legacy.channel_mask, .format = legacy.format };
-    AudioConfig aidl;
-    aidl.base = VALUE_OR_RETURN(legacy2aidl_audio_config_base_t_AudioConfigBase(base, isInput));
-    aidl.offloadInfo = VALUE_OR_RETURN(
-            legacy2aidl_audio_offload_info_t_AudioOffloadInfo(legacy.offload_info));
-    aidl.frameCount = VALUE_OR_RETURN(convertIntegral<int64_t>(legacy.frame_count));
-    return aidl;
-}
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(const AudioConfigBase& aidl, bool isInput) {
-    audio_config_base_t legacy;
-    legacy.sample_rate = VALUE_OR_RETURN(convertIntegral<uint32_t>(aidl.sampleRate));
-    legacy.channel_mask = VALUE_OR_RETURN(
-            aidl2legacy_AudioChannelLayout_audio_channel_mask_t(aidl.channelMask, isInput));
-    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
-    return legacy;
-}
-
-ConversionResult<AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput) {
-    AudioConfigBase aidl;
-    aidl.sampleRate = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.sample_rate));
-    aidl.channelMask = VALUE_OR_RETURN(
-            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-    return aidl;
-}
-
 ConversionResult<sp<IMemory>>
 aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl) {
     sp<IMemory> legacy;
@@ -2566,8 +621,8 @@
     return aidl;
 }
 
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl) {
+ConversionResult<sp<IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+        const std::optional<media::SharedFileRegion>& aidl) {
     sp<IMemory> legacy;
     if (!convertNullableSharedFileRegionToIMemory(aidl, &legacy)) {
         return unexpected(BAD_VALUE);
@@ -2602,31 +657,6 @@
     return aidl;
 }
 
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const AudioUuid& aidl) {
-    audio_uuid_t legacy;
-    legacy.timeLow = VALUE_OR_RETURN(convertReinterpret<uint32_t>(aidl.timeLow));
-    legacy.timeMid = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeMid));
-    legacy.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.timeHiAndVersion));
-    legacy.clockSeq = VALUE_OR_RETURN(convertIntegral<uint16_t>(aidl.clockSeq));
-    if (aidl.node.size() != std::size(legacy.node)) {
-        return unexpected(BAD_VALUE);
-    }
-    std::copy(aidl.node.begin(), aidl.node.end(), legacy.node);
-    return legacy;
-}
-
-ConversionResult<AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy) {
-    AudioUuid aidl;
-    aidl.timeLow = VALUE_OR_RETURN(convertReinterpret<int32_t>(legacy.timeLow));
-    aidl.timeMid = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeMid));
-    aidl.timeHiAndVersion = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.timeHiAndVersion));
-    aidl.clockSeq = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.clockSeq));
-    std::copy(legacy.node, legacy.node + std::size(legacy.node), std::back_inserter(aidl.node));
-    return aidl;
-}
-
 ConversionResult<effect_descriptor_t>
 aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl) {
     effect_descriptor_t legacy;
@@ -2657,123 +687,21 @@
     return aidl;
 }
 
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
-        AudioEncapsulationMetadataType aidl) {
-    switch (aidl) {
-        case AudioEncapsulationMetadataType::NONE:
-            return AUDIO_ENCAPSULATION_METADATA_TYPE_NONE;
-        case AudioEncapsulationMetadataType::FRAMEWORK_TUNER:
-            return AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER;
-        case AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR:
-            return AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
-        audio_encapsulation_metadata_type_t legacy) {
-    switch (legacy) {
-        case AUDIO_ENCAPSULATION_METADATA_TYPE_NONE:
-            return AudioEncapsulationMetadataType::NONE;
-        case AUDIO_ENCAPSULATION_METADATA_TYPE_FRAMEWORK_TUNER:
-            return AudioEncapsulationMetadataType::FRAMEWORK_TUNER;
-        case AUDIO_ENCAPSULATION_METADATA_TYPE_DVB_AD_DESCRIPTOR:
-            return AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl) {
-    return convertBitmask<uint32_t,
-            int32_t,
-            audio_encapsulation_mode_t,
-            AudioEncapsulationMode>(
-            aidl, aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t,
-            indexToEnum_index<AudioEncapsulationMode>,
-            enumToMask_index<uint32_t, audio_encapsulation_mode_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy) {
-    return convertBitmask<int32_t,
-            uint32_t,
-            AudioEncapsulationMode,
-            audio_encapsulation_mode_t>(
-            legacy, legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode,
-            indexToEnum_index<audio_encapsulation_mode_t>,
-            enumToMask_index<int32_t, AudioEncapsulationMode>);
-}
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl) {
-    return convertBitmask<uint32_t,
-            int32_t,
-            audio_encapsulation_metadata_type_t,
-            AudioEncapsulationMetadataType>(
-            aidl, aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t,
-            indexToEnum_index<AudioEncapsulationMetadataType>,
-            enumToMask_index<uint32_t, audio_encapsulation_metadata_type_t>);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy) {
-    return convertBitmask<int32_t,
-            uint32_t,
-            AudioEncapsulationMetadataType,
-            audio_encapsulation_metadata_type_t>(
-            legacy, legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType,
-            indexToEnum_index<audio_encapsulation_metadata_type_t>,
-            enumToMask_index<int32_t, AudioEncapsulationMetadataType>);
-}
-
-ConversionResult<audio_port_device_ext>
-aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
-        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
-    audio_port_device_ext legacy;
-    legacy.hw_module = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
-    RETURN_IF_ERROR(aidl2legacy_AudioDevice_audio_device(
-                    aidl.device, &legacy.type, legacy.address));
-    legacy.encapsulation_modes = VALUE_OR_RETURN(
-            aidl2legacy_AudioEncapsulationMode_mask(aidlSys.encapsulationModes));
-    legacy.encapsulation_metadata_types = VALUE_OR_RETURN(
-            aidl2legacy_AudioEncapsulationMetadataType_mask(
-                    aidlSys.encapsulationMetadataTypes));
-    return legacy;
-}
-
-status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
-        const audio_port_device_ext& legacy,
-        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
-    aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    aidl->device = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_device_AudioDevice(legacy.type, legacy.address));
-    aidlDeviceExt->encapsulationModes = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioEncapsulationMode_mask(legacy.encapsulation_modes));
-    aidlDeviceExt->encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioEncapsulationMetadataType_mask(legacy.encapsulation_metadata_types));
-    return OK;
-}
-
 ConversionResult<audio_port_mix_ext>
 aidl2legacy_AudioPortMixExt_audio_port_mix_ext(
         const AudioPortMixExt& aidl, const media::AudioPortMixExtSys& aidlSys) {
-    audio_port_mix_ext legacy{};
+    audio_port_mix_ext legacy = VALUE_OR_RETURN(
+            aidl2legacy_AudioPortMixExt_audio_port_mix_ext(aidl));
     legacy.hw_module = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
-    legacy.handle = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_io_handle_t(aidl.handle));
     return legacy;
 }
 
 status_t
 legacy2aidl_audio_port_mix_ext_AudioPortMixExt(const audio_port_mix_ext& legacy,
         AudioPortMixExt* aidl, media::AudioPortMixExtSys* aidlMixExt) {
+    *aidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_mix_ext_AudioPortMixExt(legacy));
     aidlMixExt->hwModule = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
-    aidl->handle = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(legacy.handle));
     return OK;
 }
 
@@ -2789,6 +717,25 @@
     return legacy2aidl_audio_session_t_int32_t(legacy.session);
 }
 
+ConversionResult<audio_port_device_ext>
+aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
+        const AudioPortDeviceExt& aidl, const media::AudioPortDeviceExtSys& aidlSys) {
+    audio_port_device_ext legacy = VALUE_OR_RETURN(
+            aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(aidl));
+    legacy.hw_module = VALUE_OR_RETURN(
+            aidl2legacy_int32_t_audio_module_handle_t(aidlSys.hwModule));
+    return legacy;
+}
+
+status_t legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(
+        const audio_port_device_ext& legacy,
+        AudioPortDeviceExt* aidl, media::AudioPortDeviceExtSys* aidlDeviceExt) {
+    *aidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_device_ext_AudioPortDeviceExt(legacy));
+    aidlDeviceExt->hwModule = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_module_handle_t_int32_t(legacy.hw_module));
+    return OK;
+}
+
 // This type is unnamed in the original definition, thus we name it here.
 using audio_port_v7_ext = decltype(audio_port_v7::ext);
 
@@ -2816,7 +763,7 @@
         case media::AudioPortType::SESSION:
             legacy.session = VALUE_OR_RETURN(
                     aidl2legacy_int32_t_audio_port_session_ext(
-                            VALUE_OR_RETURN(UNION_GET(aidl, session))));
+                            VALUE_OR_RETURN(UNION_GET(aidlSys, session))));
             return legacy;
 
     }
@@ -2852,247 +799,48 @@
             return OK;
         }
         case AUDIO_PORT_TYPE_SESSION:
-            UNION_SET(*aidl, session, VALUE_OR_RETURN_STATUS(
+            UNION_SET(*aidl, unspecified, false);
+            UNION_SET(*aidlSys, session, VALUE_OR_RETURN_STATUS(
                             legacy2aidl_audio_port_session_ext_int32_t(legacy.session)));
-            UNION_SET(*aidlSys, unspecified, false);
             return OK;
     }
     LOG_ALWAYS_FATAL("Shouldn't get here"); // with -Werror,-Wswitch may compile-time fail
 }
 
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(const AudioProfile& aidl, bool isInput) {
-    audio_profile legacy;
-    legacy.format = VALUE_OR_RETURN(aidl2legacy_AudioFormatDescription_audio_format_t(aidl.format));
-
-    if (aidl.sampleRates.size() > std::size(legacy.sample_rates)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(aidl.sampleRates.begin(), aidl.sampleRates.end(), legacy.sample_rates,
-                         convertIntegral<int32_t, unsigned int>));
-    legacy.num_sample_rates = aidl.sampleRates.size();
-
-    if (aidl.channelMasks.size() > std::size(legacy.channel_masks)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(aidl.channelMasks.begin(), aidl.channelMasks.end(), legacy.channel_masks,
-                    [isInput](const AudioChannelLayout& l) {
-                        return aidl2legacy_AudioChannelLayout_audio_channel_mask_t(l, isInput);
-                    }));
-    legacy.num_channel_masks = aidl.channelMasks.size();
-
-    legacy.encapsulation_type = VALUE_OR_RETURN(
-            aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(aidl.encapsulationType));
-    return legacy;
-}
-
-ConversionResult<AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput) {
-    AudioProfile aidl;
-    aidl.format = VALUE_OR_RETURN(legacy2aidl_audio_format_t_AudioFormatDescription(legacy.format));
-
-    if (legacy.num_sample_rates > std::size(legacy.sample_rates)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(legacy.sample_rates, legacy.sample_rates + legacy.num_sample_rates,
-                         std::back_inserter(aidl.sampleRates),
-                         convertIntegral<unsigned int, int32_t>));
-
-    if (legacy.num_channel_masks > std::size(legacy.channel_masks)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(legacy.channel_masks, legacy.channel_masks + legacy.num_channel_masks,
-                         std::back_inserter(aidl.channelMasks),
-                    [isInput](audio_channel_mask_t m) {
-                        return legacy2aidl_audio_channel_mask_t_AudioChannelLayout(m, isInput);
-                    }));
-
-    aidl.encapsulationType = VALUE_OR_RETURN(
-            legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-                    legacy.encapsulation_type));
-    return aidl;
-}
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const AudioGain& aidl, bool isInput) {
-    audio_gain legacy;
-    legacy.mode = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_gain_mode_t_mask(aidl.mode));
-    legacy.channel_mask = VALUE_OR_RETURN(aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-                    aidl.channelMask, isInput));
-    legacy.min_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.minValue));
-    legacy.max_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.maxValue));
-    legacy.default_value = VALUE_OR_RETURN(convertIntegral<int>(aidl.defaultValue));
-    legacy.step_value = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.stepValue));
-    legacy.min_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.minRampMs));
-    legacy.max_ramp_ms = VALUE_OR_RETURN(convertIntegral<unsigned int>(aidl.maxRampMs));
-    return legacy;
-}
-
-ConversionResult<AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput) {
-    AudioGain aidl;
-    aidl.mode = VALUE_OR_RETURN(legacy2aidl_audio_gain_mode_t_int32_t_mask(legacy.mode));
-    aidl.channelMask = VALUE_OR_RETURN(
-            legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy.channel_mask, isInput));
-    aidl.minValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_value));
-    aidl.maxValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_value));
-    aidl.defaultValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.default_value));
-    aidl.stepValue = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.step_value));
-    aidl.minRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.min_ramp_ms));
-    aidl.maxRampMs = VALUE_OR_RETURN(convertIntegral<int32_t>(legacy.max_ramp_ms));
-    return aidl;
-}
-
 ConversionResult<audio_port_v7>
-aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl) {
-    audio_port_v7 legacy;
-    legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.hal.id));
+aidl2legacy_AudioPortFw_audio_port_v7(const media::AudioPortFw& aidl) {
+    const bool isInput = VALUE_OR_RETURN(
+            portDirection(aidl.sys.role, aidl.sys.type)) == AudioPortDirection::INPUT;
+    audio_port_v7 legacy = VALUE_OR_RETURN(aidl2legacy_AudioPort_audio_port_v7(aidl.hal, isInput));
     legacy.role = VALUE_OR_RETURN(aidl2legacy_AudioPortRole_audio_port_role_t(aidl.sys.role));
     legacy.type = VALUE_OR_RETURN(aidl2legacy_AudioPortType_audio_port_type_t(aidl.sys.type));
-    RETURN_IF_ERROR(aidl2legacy_string(aidl.hal.name, legacy.name, sizeof(legacy.name)));
-
-    if (aidl.hal.profiles.size() > std::size(legacy.audio_profiles)) {
-        return unexpected(BAD_VALUE);
-    }
-    const bool isInput =
-            VALUE_OR_RETURN(direction(aidl.sys.role, aidl.sys.type)) == Direction::INPUT;
-    RETURN_IF_ERROR(convertRange(
-                    aidl.hal.profiles.begin(), aidl.hal.profiles.end(), legacy.audio_profiles,
-                    [isInput](const AudioProfile& p) {
-                        return aidl2legacy_AudioProfile_audio_profile(p, isInput);
-                    }));
-    legacy.num_audio_profiles = aidl.hal.profiles.size();
-
-    if (aidl.hal.extraAudioDescriptors.size() > std::size(legacy.extra_audio_descriptors)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(
-                    aidl.hal.extraAudioDescriptors.begin(), aidl.hal.extraAudioDescriptors.end(),
-                    legacy.extra_audio_descriptors,
-                    aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor));
-    legacy.num_extra_audio_descriptors = aidl.hal.extraAudioDescriptors.size();
-
-    if (aidl.hal.gains.size() > std::size(legacy.gains)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(convertRange(aidl.hal.gains.begin(), aidl.hal.gains.end(), legacy.gains,
-                                 [isInput](const AudioGain& g) {
-                                     return aidl2legacy_AudioGain_audio_gain(g, isInput);
-                                 }));
-    legacy.num_gains = aidl.hal.gains.size();
 
     legacy.active_config = VALUE_OR_RETURN(
-            aidl2legacy_AudioPortConfig_audio_port_config(aidl.sys.activeConfig));
+            aidl2legacy_AudioPortConfigFw_audio_port_config(aidl.sys.activeConfig));
     legacy.ext = VALUE_OR_RETURN(
             aidl2legacy_AudioPortExt_audio_port_v7_ext(aidl.hal.ext, aidl.sys.type, aidl.sys.ext));
     return legacy;
 }
 
-ConversionResult<media::AudioPort>
-legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy) {
-    media::AudioPort aidl;
-    aidl.hal.id = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+ConversionResult<media::AudioPortFw>
+legacy2aidl_audio_port_v7_AudioPortFw(const audio_port_v7& legacy) {
+    const bool isInput = VALUE_OR_RETURN(
+            portDirection(legacy.role, legacy.type)) == AudioPortDirection::INPUT;
+    media::AudioPortFw aidl;
+    aidl.hal = VALUE_OR_RETURN(legacy2aidl_audio_port_v7_AudioPort(legacy, isInput));
     aidl.sys.role = VALUE_OR_RETURN(legacy2aidl_audio_port_role_t_AudioPortRole(legacy.role));
     aidl.sys.type = VALUE_OR_RETURN(legacy2aidl_audio_port_type_t_AudioPortType(legacy.type));
-    aidl.hal.name = VALUE_OR_RETURN(legacy2aidl_string(legacy.name, sizeof(legacy.name)));
-
-    if (legacy.num_audio_profiles > std::size(legacy.audio_profiles)) {
-        return unexpected(BAD_VALUE);
-    }
-    const bool isInput = VALUE_OR_RETURN(direction(legacy.role, legacy.type)) == Direction::INPUT;
-    RETURN_IF_ERROR(
-            convertRange(legacy.audio_profiles, legacy.audio_profiles + legacy.num_audio_profiles,
-                         std::back_inserter(aidl.hal.profiles),
-                         [isInput](const audio_profile& p) {
-                             return legacy2aidl_audio_profile_AudioProfile(p, isInput);
-                         }));
-
-    if (legacy.num_extra_audio_descriptors > std::size(legacy.extra_audio_descriptors)) {
-        return unexpected(BAD_VALUE);
-    }
+    // These get filled by the call to 'legacy2aidl_AudioPortExt' below.
     aidl.sys.profiles.resize(legacy.num_audio_profiles);
-    RETURN_IF_ERROR(
-            convertRange(legacy.extra_audio_descriptors,
-                    legacy.extra_audio_descriptors + legacy.num_extra_audio_descriptors,
-                    std::back_inserter(aidl.hal.extraAudioDescriptors),
-                    legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor));
-
-    if (legacy.num_gains > std::size(legacy.gains)) {
-        return unexpected(BAD_VALUE);
-    }
-    RETURN_IF_ERROR(
-            convertRange(legacy.gains, legacy.gains + legacy.num_gains,
-                         std::back_inserter(aidl.hal.gains),
-                         [isInput](const audio_gain& g) {
-                             return legacy2aidl_audio_gain_AudioGain(g, isInput);
-                         }));
     aidl.sys.gains.resize(legacy.num_gains);
-
     aidl.sys.activeConfig = VALUE_OR_RETURN(
-            legacy2aidl_audio_port_config_AudioPortConfig(legacy.active_config));
+            legacy2aidl_audio_port_config_AudioPortConfigFw(legacy.active_config, legacy.id));
     aidl.sys.activeConfig.hal.portId = aidl.hal.id;
     RETURN_IF_ERROR(
             legacy2aidl_AudioPortExt(legacy.ext, legacy.type, &aidl.hal.ext, &aidl.sys.ext));
     return aidl;
 }
 
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(AudioMode aidl) {
-    switch (aidl) {
-        case AudioMode::SYS_RESERVED_INVALID:
-            return AUDIO_MODE_INVALID;
-        case AudioMode::SYS_RESERVED_CURRENT:
-            return AUDIO_MODE_CURRENT;
-        case AudioMode::NORMAL:
-            return AUDIO_MODE_NORMAL;
-        case AudioMode::RINGTONE:
-            return AUDIO_MODE_RINGTONE;
-        case AudioMode::IN_CALL:
-            return AUDIO_MODE_IN_CALL;
-        case AudioMode::IN_COMMUNICATION:
-            return AUDIO_MODE_IN_COMMUNICATION;
-        case AudioMode::CALL_SCREEN:
-            return AUDIO_MODE_CALL_SCREEN;
-        case AudioMode::SYS_RESERVED_CALL_REDIRECT:
-            return AUDIO_MODE_CALL_REDIRECT;
-        case AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT:
-            return AUDIO_MODE_COMMUNICATION_REDIRECT;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_MODE_INVALID:
-            return AudioMode::SYS_RESERVED_INVALID;
-        case AUDIO_MODE_CURRENT:
-            return AudioMode::SYS_RESERVED_CURRENT;
-        case AUDIO_MODE_NORMAL:
-            return AudioMode::NORMAL;
-        case AUDIO_MODE_RINGTONE:
-            return AudioMode::RINGTONE;
-        case AUDIO_MODE_IN_CALL:
-            return AudioMode::IN_CALL;
-        case AUDIO_MODE_IN_COMMUNICATION:
-            return AudioMode::IN_COMMUNICATION;
-        case AUDIO_MODE_CALL_SCREEN:
-            return AudioMode::CALL_SCREEN;
-        case AUDIO_MODE_CALL_REDIRECT:
-            return AudioMode::SYS_RESERVED_CALL_REDIRECT;
-        case AUDIO_MODE_COMMUNICATION_REDIRECT:
-            return AudioMode::SYS_RESERVED_COMMUNICATION_REDIRECT;
-        case AUDIO_MODE_CNT:
-            break;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<audio_unique_id_use_t>
 aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl) {
     switch (aidl) {
@@ -3161,160 +909,6 @@
     return convertReinterpret<int32_t>(legacy);
 }
 
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl) {
-    switch (aidl) {
-        case media::AudioDualMonoMode::OFF:
-            return AUDIO_DUAL_MONO_MODE_OFF;
-        case media::AudioDualMonoMode::LR:
-            return AUDIO_DUAL_MONO_MODE_LR;
-        case media::AudioDualMonoMode::LL:
-            return AUDIO_DUAL_MONO_MODE_LL;
-        case media::AudioDualMonoMode::RR:
-            return AUDIO_DUAL_MONO_MODE_RR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_DUAL_MONO_MODE_OFF:
-            return media::AudioDualMonoMode::OFF;
-        case AUDIO_DUAL_MONO_MODE_LR:
-            return media::AudioDualMonoMode::LR;
-        case AUDIO_DUAL_MONO_MODE_LL:
-            return media::AudioDualMonoMode::LL;
-        case AUDIO_DUAL_MONO_MODE_RR:
-            return media::AudioDualMonoMode::RR;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl) {
-    return convertReinterpret<audio_timestretch_fallback_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl) {
-    return convertReinterpret<audio_timestretch_stretch_mode_t>(aidl);
-}
-
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy) {
-    return convertReinterpret<int32_t>(legacy);
-}
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl) {
-    audio_playback_rate_t legacy;
-    legacy.mSpeed = aidl.speed;
-    legacy.mPitch = aidl.pitch;
-    legacy.mFallbackMode = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(aidl.fallbackMode));
-    legacy.mStretchMode = VALUE_OR_RETURN(
-            aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(aidl.stretchMode));
-    return legacy;
-}
-
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy) {
-    media::AudioPlaybackRate aidl;
-    aidl.speed = legacy.mSpeed;
-    aidl.pitch = legacy.mPitch;
-    aidl.fallbackMode = VALUE_OR_RETURN(
-            legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(legacy.mFallbackMode));
-    aidl.stretchMode = VALUE_OR_RETURN(
-            legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(legacy.mStretchMode));
-    return aidl;
-}
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(AudioStandard aidl) {
-    switch (aidl) {
-        case AudioStandard::NONE:
-            return AUDIO_STANDARD_NONE;
-        case AudioStandard::EDID:
-            return AUDIO_STANDARD_EDID;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy) {
-    switch (legacy) {
-        case AUDIO_STANDARD_NONE:
-            return AudioStandard::NONE;
-        case AUDIO_STANDARD_EDID:
-            return AudioStandard::EDID;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
-        const ExtraAudioDescriptor& aidl) {
-    audio_extra_audio_descriptor legacy;
-    legacy.standard = VALUE_OR_RETURN(aidl2legacy_AudioStandard_audio_standard_t(aidl.standard));
-    if (aidl.audioDescriptor.size() > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
-        return unexpected(BAD_VALUE);
-    }
-    legacy.descriptor_length = aidl.audioDescriptor.size();
-    std::copy(aidl.audioDescriptor.begin(), aidl.audioDescriptor.end(),
-              std::begin(legacy.descriptor));
-    legacy.encapsulation_type =
-            VALUE_OR_RETURN(aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
-                    aidl.encapsulationType));
-    return legacy;
-}
-
-ConversionResult<ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
-        const audio_extra_audio_descriptor& legacy) {
-    ExtraAudioDescriptor aidl;
-    aidl.standard = VALUE_OR_RETURN(legacy2aidl_audio_standard_t_AudioStandard(legacy.standard));
-    if (legacy.descriptor_length > EXTRA_AUDIO_DESCRIPTOR_SIZE) {
-        return unexpected(BAD_VALUE);
-    }
-    aidl.audioDescriptor.resize(legacy.descriptor_length);
-    std::copy(legacy.descriptor, legacy.descriptor + legacy.descriptor_length,
-              aidl.audioDescriptor.begin());
-    aidl.encapsulationType =
-            VALUE_OR_RETURN(legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-                    legacy.encapsulation_type));
-    return aidl;
-}
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
-        const AudioEncapsulationType& aidl) {
-    switch (aidl) {
-        case AudioEncapsulationType::NONE:
-            return AUDIO_ENCAPSULATION_TYPE_NONE;
-        case AudioEncapsulationType::IEC61937:
-            return AUDIO_ENCAPSULATION_TYPE_IEC61937;
-    }
-    return unexpected(BAD_VALUE);
-}
-
-ConversionResult<AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-        const audio_encapsulation_type_t & legacy) {
-    switch (legacy) {
-        case AUDIO_ENCAPSULATION_TYPE_NONE:
-            return AudioEncapsulationType::NONE;
-        case AUDIO_ENCAPSULATION_TYPE_IEC61937:
-            return AudioEncapsulationType::IEC61937;
-    }
-    return unexpected(BAD_VALUE);
-}
-
 ConversionResult<TrackSecondaryOutputInfoPair>
 aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
         const media::TrackSecondaryOutputInfo& aidl) {
@@ -3388,24 +982,23 @@
             enumToMask_index<int32_t, media::AudioDirectMode>);
 }
 
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl) {
-    switch (aidl) {
-        case media::LatencyMode::FREE:
-            return AUDIO_LATENCY_MODE_FREE;
-        case media::LatencyMode::LOW:
-            return AUDIO_LATENCY_MODE_LOW;
-    }
-    return unexpected(BAD_VALUE);
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(
+        const media::MicrophoneInfoFw& aidl) {
+    audio_microphone_characteristic_t legacy =
+            VALUE_OR_RETURN(aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+                            aidl.info, aidl.dynamic));
+    legacy.id = VALUE_OR_RETURN(aidl2legacy_int32_t_audio_port_handle_t(aidl.portId));
+    return legacy;
 }
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy) {
-    switch (legacy) {
-        case AUDIO_LATENCY_MODE_FREE:
-            return media::LatencyMode::FREE;
-        case AUDIO_LATENCY_MODE_LOW:
-            return media::LatencyMode::LOW;
-    }
-    return unexpected(BAD_VALUE);
+ConversionResult<media::MicrophoneInfoFw>
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+        const audio_microphone_characteristic_t& legacy) {
+    media::MicrophoneInfoFw aidl;
+    RETURN_IF_ERROR(legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfos(
+                    legacy, &aidl.info, &aidl.dynamic));
+    aidl.portId = VALUE_OR_RETURN(legacy2aidl_audio_port_handle_t_int32_t(legacy.id));
+    return aidl;
 }
+
 }  // namespace android
diff --git a/media/libaudioclient/Android.bp b/media/libaudioclient/Android.bp
index dccef0e..30658f7 100644
--- a/media/libaudioclient/Android.bp
+++ b/media/libaudioclient/Android.bp
@@ -54,8 +54,10 @@
         "AudioVolumeGroup.cpp",
         "PolicyAidlConversion.cpp"
     ],
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_export_shared",
+    ],
     shared_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
         "audiopolicy-aidl-cpp",
@@ -76,7 +78,6 @@
     include_dirs: ["system/media/audio_utils/include"],
     export_include_dirs: ["include"],
     export_shared_lib_headers: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
         "audiopolicy-aidl-cpp",
@@ -116,8 +117,10 @@
         "RecordingActivityTracker.cpp",
         "TrackPlayerBase.cpp",
     ],
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
     shared_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
         "audiopolicy-aidl-cpp",
@@ -125,6 +128,7 @@
         "audiopolicy-types-aidl-cpp",
         "av-types-aidl-cpp",
         "capture_state_listener-aidl-cpp",
+        "libaudio_aidl_conversion_common_cpp",
         "libaudioclient_aidl_conversion",
         "libaudiofoundation",
         "libaudioutils",
@@ -190,87 +194,31 @@
     },
 }
 
-// This is intended for clients needing to include AidlConversionUtil.h, without dragging in a lot of extra
-// dependencies.
-cc_library_headers {
-    name: "libaudioclient_aidl_conversion_util",
-    host_supported: true,
-    vendor_available: true,
-    double_loadable: true,
-    min_sdk_version: "29",
-    export_include_dirs: [
-        "include",
-    ],
-    header_libs: [
-        "libbase_headers",
-        "liberror_headers",
-    ],
-    export_header_lib_headers: [
-        "libbase_headers",
-        "liberror_headers",
-    ],
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.bluetooth",
-        "com.android.media",
-        "com.android.media.swcodec",
-    ],
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-}
-
 cc_library {
     name: "libaudioclient_aidl_conversion",
     srcs: ["AidlConversion.cpp"],
+    shared_libs: [
+        "audioclient-types-aidl-cpp",
+        "av-types-aidl-cpp",
+    ],
+    static_libs: [
+        "libaudio_aidl_conversion_common_cpp",
+    ],
     export_include_dirs: ["include"],
-    host_supported: true,
-    vendor_available: true,
-    double_loadable: true,
-    min_sdk_version: "29",
     header_libs: [
-        "libaudioclient_aidl_conversion_util",
-        "libaudio_system_headers",
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     export_header_lib_headers: [
-        "libaudioclient_aidl_conversion_util",
-    ],
-    shared_libs: [
-        "android.media.audio.common.types-V1-cpp",
-        "audioclient-types-aidl-cpp",
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libshmemcompat",
-        "libstagefright_foundation",
-        "libutils",
-        "shared-file-region-aidl-cpp",
-        "framework-permission-aidl-cpp",
+        "libaudio_aidl_conversion_common_util_cpp",
     ],
     export_shared_lib_headers: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
-        "libbase",
-        "shared-file-region-aidl-cpp",
+        "av-types-aidl-cpp",
     ],
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-error=deprecated-declarations",
+    defaults: [
+        "audio_aidl_conversion_common_default",
+        "latest_android_media_audio_common_types_cpp_export_shared",
     ],
-    sanitize: {
-        misc_undefined: [
-            "unsigned-integer-overflow",
-            "signed-integer-overflow",
-        ],
-    },
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
 }
 
 // AIDL interface between libaudioclient and framework.jar
@@ -278,6 +226,7 @@
     name: "libaudioclient_aidl",
     srcs: [
         "aidl/android/media/IPlayer.aidl",
+        "aidl/android/media/AudioHalVersion.aidl",
     ],
     path: "aidl",
 }
@@ -302,12 +251,26 @@
     double_loadable: true,
     vendor_available: true,
     srcs: [
+        "aidl/android/media/EffectConfig.aidl",
         "aidl/android/media/IEffect.aidl",
         "aidl/android/media/IEffectClient.aidl",
     ],
     imports: [
+        "android.media.audio.common.types-V2",
         "shared-file-region-aidl",
     ],
+    backend: {
+        cpp: {
+            min_sdk_version: "29",
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media",
+            ],
+        },
+        java: {
+            sdk_version: "module_current",
+        },
+    },
 }
 
 aidl_interface {
@@ -321,16 +284,15 @@
         "aidl/android/media/AudioAttributesInternal.aidl",
         "aidl/android/media/AudioClient.aidl",
         "aidl/android/media/AudioDirectMode.aidl",
-        "aidl/android/media/AudioDualMonoMode.aidl",
         "aidl/android/media/AudioFlag.aidl",
         "aidl/android/media/AudioGainSys.aidl",
+        "aidl/android/media/AudioHalVersion.aidl",
         "aidl/android/media/AudioIoConfigEvent.aidl",
         "aidl/android/media/AudioIoDescriptor.aidl",
-        "aidl/android/media/AudioPatch.aidl",
-        "aidl/android/media/AudioPlaybackRate.aidl",
-        "aidl/android/media/AudioPort.aidl",
+        "aidl/android/media/AudioPatchFw.aidl",
+        "aidl/android/media/AudioPortFw.aidl",
         "aidl/android/media/AudioPortSys.aidl",
-        "aidl/android/media/AudioPortConfig.aidl",
+        "aidl/android/media/AudioPortConfigFw.aidl",
         "aidl/android/media/AudioPortConfigSys.aidl",
         "aidl/android/media/AudioPortDeviceExtSys.aidl",
         "aidl/android/media/AudioPortExtSys.aidl",
@@ -342,11 +304,10 @@
         "aidl/android/media/AudioUniqueIdUse.aidl",
         "aidl/android/media/AudioVibratorInfo.aidl",
         "aidl/android/media/EffectDescriptor.aidl",
-        "aidl/android/media/LatencyMode.aidl",
         "aidl/android/media/TrackSecondaryOutputInfo.aidl",
     ],
     imports: [
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
         "framework-permission-aidl",
     ],
     backend: {
@@ -390,7 +351,7 @@
         "aidl/android/media/SpatializerHeadTrackingMode.aidl",
     ],
     imports: [
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
         "audioclient-types-aidl",
     ],
     backend: {
@@ -433,7 +394,7 @@
         "aidl/android/media/IAudioTrackCallback.aidl",
     ],
     imports: [
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
         "audioclient-types-aidl",
         "av-types-aidl",
         "effect-aidl",
@@ -470,7 +431,7 @@
         "aidl/android/media/IAudioPolicyServiceClient.aidl",
     ],
     imports: [
-        "android.media.audio.common.types-V1",
+        "android.media.audio.common.types-V2",
         "audioclient-types-aidl",
         "audiopolicy-types-aidl",
         "capture_state_listener-aidl",
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index dc21c52..2870c4c 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -89,7 +89,7 @@
         return NO_INIT;
     }
 
-    if (type == NULL && uuid == NULL) {
+    if (type == nullptr && uuid == nullptr) {
         ALOGW("Must specify at least type or uuid");
         return BAD_VALUE;
     }
@@ -99,8 +99,8 @@
     mCallback = callback;
 
     memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
-    mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
-    mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);
+    mDescriptor.type = *(type != nullptr ? type : EFFECT_UUID_NULL);
+    mDescriptor.uuid = *(uuid != nullptr ? uuid : EFFECT_UUID_NULL);
 
     // TODO b/182392769: use attribution source util
     mIEffectClient = new EffectClient(this);
@@ -292,7 +292,7 @@
             AudioSystem::releaseAudioSessionId(mSessionId,
                 VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientAttributionSource.pid)));
         }
-        if (mIEffect != NULL) {
+        if (mIEffect != nullptr) {
             mIEffect->disconnect();
             IInterface::asBinder(mIEffect)->unlinkToDeath(mIEffectClient);
         }
@@ -370,7 +370,7 @@
         if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
             return NO_ERROR;
         }
-        if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
+        if (replySize == nullptr || *replySize != sizeof(status_t) || replyData == nullptr) {
             return BAD_VALUE;
         }
         mLock.lock();
@@ -413,7 +413,7 @@
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
 
-    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+    if (param == nullptr || param->psize == 0 || param->vsize == 0) {
         return BAD_VALUE;
     }
 
@@ -448,8 +448,7 @@
     if (mStatus != NO_ERROR) {
         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
     }
-
-    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+    if (param == nullptr || param->psize == 0 || param->vsize == 0) {
         return BAD_VALUE;
     }
 
@@ -504,8 +503,7 @@
     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
         return mStatus;
     }
-
-    if (param == NULL || param->psize == 0 || param->vsize == 0) {
+    if (param == nullptr || param->psize == 0 || param->vsize == 0) {
         return BAD_VALUE;
     }
 
@@ -529,6 +527,36 @@
     return status;
 }
 
+status_t AudioEffect::getConfigs(
+        audio_config_base_t *inputCfg, audio_config_base_t *outputCfg)
+{
+    if (mProbe) {
+        return INVALID_OPERATION;
+    }
+    if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+        return mStatus;
+    }
+    if (inputCfg == NULL || outputCfg == NULL) {
+        return BAD_VALUE;
+    }
+    status_t status;
+    media::EffectConfig cfg;
+    Status bs = mIEffect->getConfig(&cfg, &status);
+    if (!bs.isOk()) {
+        status = statusTFromBinderStatus(bs);
+        ALOGW("%s received status %d from binder transaction", __func__, status);
+        return status;
+    }
+    if (status == NO_ERROR) {
+        *inputCfg = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioConfigBase_audio_config_base_t(
+                        cfg.inputCfg, cfg.isOnInputStream));
+        *outputCfg = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioConfigBase_audio_config_base_t(
+                        cfg.outputCfg, cfg.isOnInputStream));
+    } else {
+        ALOGW("%s received status %d from the effect", __func__, status);
+    }
+    return status;
+}
 
 // -------------------------------------------------------------------------
 
@@ -602,6 +630,9 @@
 
 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
 {
+    if (numEffects == nullptr) {
+        return BAD_VALUE;
+    }
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     return af->queryNumberEffects(numEffects);
@@ -609,6 +640,9 @@
 
 status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
 {
+    if (descriptor == nullptr) {
+        return BAD_VALUE;
+    }
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     return af->queryEffect(index, descriptor);
@@ -619,6 +653,9 @@
                                           uint32_t preferredTypeFlag,
                                           effect_descriptor_t *descriptor)
 {
+    if (uuid == nullptr || type == nullptr || descriptor == nullptr) {
+        return BAD_VALUE;
+    }
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     return af->getEffectDescriptor(uuid, type, preferredTypeFlag, descriptor);
@@ -649,6 +686,9 @@
 
 status_t AudioEffect::newEffectUniqueId(audio_unique_id_t* id)
 {
+    if (id == nullptr) {
+        return BAD_VALUE;
+    }
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     *id = af->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
@@ -662,14 +702,15 @@
                                              audio_source_t source,
                                              audio_unique_id_t *id)
 {
+    if ((typeStr == nullptr && uuidStr == nullptr) || id == nullptr) {
+        return BAD_VALUE;
+    }
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
-
     // Convert type & uuid from string to effect_uuid_t.
     effect_uuid_t type;
-    if (typeStr != NULL) {
+    if (typeStr != nullptr) {
         status_t res = stringToGuid(typeStr, &type);
         if (res != OK) return res;
     } else {
@@ -677,7 +718,7 @@
     }
 
     effect_uuid_t uuid;
-    if (uuidStr != NULL) {
+    if (uuidStr != nullptr) {
         status_t res = stringToGuid(uuidStr, &uuid);
         if (res != OK) return res;
     } else {
@@ -705,14 +746,15 @@
                                              audio_usage_t usage,
                                              audio_unique_id_t *id)
 {
+    if ((typeStr == nullptr && uuidStr == nullptr) || id == nullptr) {
+        return BAD_VALUE;
+    }
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
-
     // Convert type & uuid from string to effect_uuid_t.
     effect_uuid_t type;
-    if (typeStr != NULL) {
+    if (typeStr != nullptr) {
         status_t res = stringToGuid(typeStr, &type);
         if (res != OK) return res;
     } else {
@@ -720,7 +762,7 @@
     }
 
     effect_uuid_t uuid;
-    if (uuidStr != NULL) {
+    if (uuidStr != nullptr) {
         status_t res = stringToGuid(uuidStr, &uuid);
         if (res != OK) return res;
     } else {
@@ -763,7 +805,7 @@
 
 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
 {
-    if (str == NULL || guid == NULL) {
+    if (str == nullptr || guid == nullptr) {
         return BAD_VALUE;
     }
 
@@ -789,7 +831,7 @@
 
 status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
 {
-    if (guid == NULL || str == NULL) {
+    if (guid == nullptr || str == nullptr) {
         return BAD_VALUE;
     }
 
diff --git a/media/libaudioclient/AudioPolicy.cpp b/media/libaudioclient/AudioPolicy.cpp
index c2f7229..4d2b6b1 100644
--- a/media/libaudioclient/AudioPolicy.cpp
+++ b/media/libaudioclient/AudioPolicy.cpp
@@ -71,6 +71,10 @@
     return NO_ERROR;
 }
 
+bool AudioMixMatchCriterion::isExcludeCriterion() const {
+    return mRule & RULE_EXCLUSION_MASK;
+}
+
 //
 //  AudioMix implementation
 //
@@ -91,10 +95,11 @@
     if (size > MAX_CRITERIA_PER_MIX) {
         size = MAX_CRITERIA_PER_MIX;
     }
+    mCriteria.reserve(size);
     for (size_t i = 0; i < size; i++) {
         AudioMixMatchCriterion criterion;
         if (criterion.readFromParcel(parcel) == NO_ERROR) {
-            mCriteria.add(criterion);
+            mCriteria.push_back(criterion);
         }
     }
     return NO_ERROR;
@@ -135,18 +140,18 @@
     return NO_ERROR;
 }
 
-void AudioMix::setExcludeUid(uid_t uid) const {
+void AudioMix::setExcludeUid(uid_t uid) {
     AudioMixMatchCriterion crit;
     crit.mRule = RULE_EXCLUDE_UID;
     crit.mValue.mUid = uid;
-    mCriteria.add(crit);
+    mCriteria.push_back(crit);
 }
 
-void AudioMix::setMatchUid(uid_t uid) const {
+void AudioMix::setMatchUid(uid_t uid) {
     AudioMixMatchCriterion crit;
     crit.mRule = RULE_MATCH_UID;
     crit.mValue.mUid = uid;
-    mCriteria.add(crit);
+    mCriteria.push_back(crit);
 }
 
 bool AudioMix::hasUidRule(bool match, uid_t uid) const {
@@ -169,18 +174,18 @@
     return false;
 }
 
-void AudioMix::setExcludeUserId(int userId) const {
+void AudioMix::setExcludeUserId(int userId) {
     AudioMixMatchCriterion crit;
     crit.mRule = RULE_EXCLUDE_USERID;
     crit.mValue.mUserId = userId;
-    mCriteria.add(crit);
+    mCriteria.push_back(crit);
 }
 
-void AudioMix::setMatchUserId(int userId) const {
+void AudioMix::setMatchUserId(int userId) {
     AudioMixMatchCriterion crit;
     crit.mRule = RULE_MATCH_USERID;
     crit.mValue.mUserId = userId;
-    mCriteria.add(crit);
+    mCriteria.push_back(crit);
 }
 
 bool AudioMix::hasUserIdRule(bool match, int userId) const {
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 15203d6..91b54a8 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -146,39 +146,6 @@
         audio_channel_mask_t channelMask,
         const AttributionSourceState& client,
         size_t frameCount,
-        legacy_callback_t callback,
-        void* user,
-        uint32_t notificationFrames,
-        audio_session_t sessionId,
-        transfer_type transferType,
-        audio_input_flags_t flags,
-        const audio_attributes_t* pAttributes,
-        audio_port_handle_t selectedDeviceId,
-        audio_microphone_direction_t selectedMicDirection,
-        float microphoneFieldDimension)
-    : mActive(false),
-      mStatus(NO_INIT),
-      mClientAttributionSource(client),
-      mSessionId(AUDIO_SESSION_ALLOCATE),
-      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT),
-      mProxy(NULL)
-{
-    uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mClientAttributionSource.uid));
-    pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientAttributionSource.pid));
-    (void)set(inputSource, sampleRate, format, channelMask, frameCount, callback, user,
-            notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
-            uid, pid, pAttributes, selectedDeviceId, selectedMicDirection,
-            microphoneFieldDimension);
-}
-
-AudioRecord::AudioRecord(
-        audio_source_t inputSource,
-        uint32_t sampleRate,
-        audio_format_t format,
-        audio_channel_mask_t channelMask,
-        const AttributionSourceState& client,
-        size_t frameCount,
         const wp<IAudioRecordCallback>& callback,
         uint32_t notificationFrames,
         audio_session_t sessionId,
@@ -255,37 +222,6 @@
         mDeviceCallback.clear();
     }
 }
-namespace {
-class LegacyCallbackWrapper : public AudioRecord::IAudioRecordCallback {
-    const AudioRecord::legacy_callback_t mCallback;
-    void* const mData;
-
-  public:
-    LegacyCallbackWrapper(AudioRecord::legacy_callback_t callback, void* user)
-        : mCallback(callback), mData(user) {}
-
-    size_t onMoreData(const AudioRecord::Buffer& buffer) override {
-        AudioRecord::Buffer copy = buffer;
-        mCallback(AudioRecord::EVENT_MORE_DATA, mData, &copy);
-        return copy.size();
-    }
-
-    void onOverrun() override { mCallback(AudioRecord::EVENT_OVERRUN, mData, nullptr); }
-
-    void onMarker(uint32_t markerPosition) override {
-        mCallback(AudioRecord::EVENT_MARKER, mData, &markerPosition);
-    }
-
-    void onNewPos(uint32_t newPos) override {
-        mCallback(AudioRecord::EVENT_NEW_POS, mData, &newPos);
-    }
-
-    void onNewIAudioRecord() override {
-        mCallback(AudioRecord::EVENT_NEW_IAUDIORECORD, mData, nullptr);
-    }
-};
-}  // namespace
-
 status_t AudioRecord::set(
         audio_source_t inputSource,
         uint32_t sampleRate,
@@ -479,37 +415,6 @@
     return status;
 }
 
-status_t AudioRecord::set(
-        audio_source_t inputSource,
-        uint32_t sampleRate,
-        audio_format_t format,
-        audio_channel_mask_t channelMask,
-        size_t frameCount,
-        legacy_callback_t callback,
-        void* user,
-        uint32_t notificationFrames,
-        bool threadCanCallJava,
-        audio_session_t sessionId,
-        transfer_type transferType,
-        audio_input_flags_t flags,
-        uid_t uid,
-        pid_t pid,
-        const audio_attributes_t* pAttributes,
-        audio_port_handle_t selectedDeviceId,
-        audio_microphone_direction_t selectedMicDirection,
-        float microphoneFieldDimension,
-        int32_t maxSharedAudioHistoryMs)
-{
-    if (callback != nullptr) {
-        mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
-    } else if (user) {
-        LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
-    }
-    return set(inputSource, sampleRate, format, channelMask, frameCount, mLegacyCallbackWrapper,
-        notificationFrames, threadCanCallJava, sessionId, transferType, flags, uid, pid,
-        pAttributes, selectedDeviceId, selectedMicDirection, microphoneFieldDimension,
-        maxSharedAudioHistoryMs);
-}
 // -------------------------------------------------------------------------
 
 status_t AudioRecord::start(AudioSystem::sync_event_t event, audio_session_t triggerSession)
@@ -1712,16 +1617,10 @@
 
 // -------------------------------------------------------------------------
 
-status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+status_t AudioRecord::getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones)
 {
     AutoMutex lock(mLock);
-    std::vector<media::MicrophoneInfoData> mics;
-    status_t status = statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(&mics));
-    activeMicrophones->resize(mics.size());
-    for (size_t i = 0; status == OK && i < mics.size(); ++i) {
-        status = activeMicrophones->at(i).readFromParcelable(mics[i]);
-    }
-    return status;
+    return statusTFromBinderStatus(mAudioRecord->getActiveMicrophones(activeMicrophones));
 }
 
 status_t AudioRecord::setPreferredMicrophoneDirection(audio_microphone_direction_t direction)
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index bacca3a..6ffbdc4 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -671,12 +671,12 @@
 }
 
 Status AudioSystem::AudioFlingerClient::onSupportedLatencyModesChanged(
-        int output, const std::vector<media::LatencyMode>& latencyModes) {
+        int output, const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     std::vector<audio_latency_mode_t> modesLegacy = VALUE_OR_RETURN_BINDER_STATUS(
             convertContainer<std::vector<audio_latency_mode_t>>(
-                    latencyModes, aidl2legacy_LatencyMode_audio_latency_mode_t));
+                    latencyModes, aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
 
     std::vector<sp<SupportedLatencyModesCallback>> callbacks;
     {
@@ -1532,7 +1532,7 @@
             legacy2aidl_audio_port_type_t_AudioPortType(type));
     Int numPortsAidl;
     numPortsAidl.value = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_ports));
-    std::vector<media::AudioPort> portsAidl;
+    std::vector<media::AudioPortFw> portsAidl;
     int32_t generationAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -1540,7 +1540,7 @@
     *num_ports = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(numPortsAidl.value));
     *generation = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(generationAidl));
     RETURN_STATUS_IF_ERROR(convertRange(portsAidl.begin(), portsAidl.end(), ports,
-                                        aidl2legacy_AudioPort_audio_port_v7));
+                                        aidl2legacy_AudioPortFw_audio_port_v7));
     return OK;
 }
 
@@ -1551,10 +1551,10 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioPort portAidl;
+    media::AudioPortFw portAidl;
     RETURN_STATUS_IF_ERROR(
             statusTFromBinderStatus(aps->getAudioPort(port->id, &portAidl)));
-    *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPort_audio_port_v7(portAidl));
+    *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortFw_audio_port_v7(portAidl));
     return OK;
 }
 
@@ -1567,8 +1567,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioPatch patchAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_patch_AudioPatch(*patch));
+    media::AudioPatchFw patchAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_patch_AudioPatchFw(*patch));
     int32_t handleAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_handle_t_int32_t(*handle));
     RETURN_STATUS_IF_ERROR(
             statusTFromBinderStatus(aps->createAudioPatch(patchAidl, handleAidl, &handleAidl)));
@@ -1598,7 +1598,7 @@
 
     Int numPatchesAidl;
     numPatchesAidl.value = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_patches));
-    std::vector<media::AudioPatch> patchesAidl;
+    std::vector<media::AudioPatchFw> patchesAidl;
     int32_t generationAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -1606,7 +1606,7 @@
     *num_patches = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(numPatchesAidl.value));
     *generation = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(generationAidl));
     RETURN_STATUS_IF_ERROR(convertRange(patchesAidl.begin(), patchesAidl.end(), patches,
-                                        aidl2legacy_AudioPatch_audio_patch));
+                                        aidl2legacy_AudioPatchFw_audio_patch));
     return OK;
 }
 
@@ -1618,8 +1618,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_port_config_AudioPortConfig(*config));
+    media::AudioPortConfigFw configAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_config_AudioPortConfigFw(*config));
     return statusTFromBinderStatus(aps->setAudioPortConfig(configAidl));
 }
 
@@ -1839,8 +1839,8 @@
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
-    media::AudioPortConfig sourceAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_port_config_AudioPortConfig(*source));
+    media::AudioPortConfigFw sourceAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_config_AudioPortConfigFw(*source));
     media::AudioAttributesInternal attributesAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_attributes_t_AudioAttributesInternal(*attributes));
     int32_t portIdAidl;
@@ -1904,7 +1904,7 @@
     return result.value_or(NAN);
 }
 
-status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
+status_t AudioSystem::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
     if (af == 0) return PERMISSION_DENIED;
     return af->getMicrophones(microphones);
@@ -2339,6 +2339,9 @@
                                     const AudioDeviceTypeAddrVector &devices,
                                     bool *canBeSpatialized) {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (canBeSpatialized == nullptr) {
+        return BAD_VALUE;
+    }
     if (aps == 0) {
         return PERMISSION_DENIED;
     }
@@ -2384,7 +2387,7 @@
 
 status_t AudioSystem::getDirectProfilesForAttributes(const audio_attributes_t* attr,
                                                 std::vector<audio_profile>* audioProfiles) {
-    if (attr == nullptr) {
+    if (attr == nullptr || audioProfiles == nullptr) {
         return BAD_VALUE;
     }
 
@@ -2423,6 +2426,32 @@
     return af->getSupportedLatencyModes(output, modes);
 }
 
+status_t AudioSystem::setBluetoothVariableLatencyEnabled(bool enabled) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == nullptr) {
+        return PERMISSION_DENIED;
+    }
+    return af->setBluetoothVariableLatencyEnabled(enabled);
+}
+
+status_t AudioSystem::isBluetoothVariableLatencyEnabled(
+        bool *enabled) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == nullptr) {
+        return PERMISSION_DENIED;
+    }
+    return af->isBluetoothVariableLatencyEnabled(enabled);
+}
+
+status_t AudioSystem::supportsBluetoothVariableLatency(
+        bool *support) {
+    const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+    if (af == nullptr) {
+        return PERMISSION_DENIED;
+    }
+    return af->supportsBluetoothVariableLatency(support);
+}
+
 class CaptureStateListenerImpl : public media::BnCaptureStateListener,
                                  public IBinder::DeathRecipient {
 public:
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index 6ab8339..ff4b071 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -325,45 +325,6 @@
         }
     };
 }
-
-AudioTrack::AudioTrack(
-        audio_stream_type_t streamType,
-        uint32_t sampleRate,
-        audio_format_t format,
-        audio_channel_mask_t channelMask,
-        size_t frameCount,
-        audio_output_flags_t flags,
-        legacy_callback_t callback,
-        void* user,
-        int32_t notificationFrames,
-        audio_session_t sessionId,
-        transfer_type transferType,
-        const audio_offload_info_t *offloadInfo,
-        const AttributionSourceState& attributionSource,
-        const audio_attributes_t* pAttributes,
-        bool doNotReconnect,
-        float maxRequiredSpeed,
-        audio_port_handle_t selectedDeviceId)
-    : mStatus(NO_INIT),
-      mState(STATE_STOPPED),
-      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT),
-      mPausedPosition(0),
-      mAudioTrackCallback(new AudioTrackCallback())
-{
-    mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
-    if (callback != nullptr) {
-        mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
-    } else if (user) {
-        LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
-    }
-    mSetParams = std::unique_ptr<SetParams>{new SetParams{
-            streamType, sampleRate, format, channelMask, frameCount, flags, mLegacyCallbackWrapper,
-            notificationFrames, 0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId,
-            transferType, offloadInfo, attributionSource, pAttributes, doNotReconnect,
-            maxRequiredSpeed, selectedDeviceId}};
-}
-
 AudioTrack::AudioTrack(
         audio_stream_type_t streamType,
         uint32_t sampleRate,
@@ -397,44 +358,6 @@
                           doNotReconnect, maxRequiredSpeed, AUDIO_PORT_HANDLE_NONE}};
 }
 
-AudioTrack::AudioTrack(
-        audio_stream_type_t streamType,
-        uint32_t sampleRate,
-        audio_format_t format,
-        audio_channel_mask_t channelMask,
-        const sp<IMemory>& sharedBuffer,
-        audio_output_flags_t flags,
-        legacy_callback_t callback,
-        void* user,
-        int32_t notificationFrames,
-        audio_session_t sessionId,
-        transfer_type transferType,
-        const audio_offload_info_t *offloadInfo,
-        const AttributionSourceState& attributionSource,
-        const audio_attributes_t* pAttributes,
-        bool doNotReconnect,
-        float maxRequiredSpeed)
-    : mStatus(NO_INIT),
-      mState(STATE_STOPPED),
-      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
-      mPreviousSchedulingGroup(SP_DEFAULT),
-      mPausedPosition(0),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mAudioTrackCallback(new AudioTrackCallback())
-{
-    mAttributes = AUDIO_ATTRIBUTES_INITIALIZER;
-    if (callback) {
-        mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
-    } else if (user) {
-        LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
-    }
-    mSetParams = std::unique_ptr<SetParams>{new SetParams{
-            streamType, sampleRate, format, channelMask, 0 /*frameCount*/, flags,
-            mLegacyCallbackWrapper, notificationFrames, sharedBuffer, false /*threadCanCallJava*/,
-            sessionId, transferType, offloadInfo, attributionSource, pAttributes, doNotReconnect,
-            maxRequiredSpeed, AUDIO_PORT_HANDLE_NONE}};
-}
-
 void AudioTrack::onFirstRef() {
     if (mSetParams) {
         set(*mSetParams);
@@ -496,38 +419,6 @@
         mDeviceCallback.clear();
     }
 }
-
-status_t AudioTrack::set(
-        audio_stream_type_t streamType,
-        uint32_t sampleRate,
-        audio_format_t format,
-        audio_channel_mask_t channelMask,
-        size_t frameCount,
-        audio_output_flags_t flags,
-        legacy_callback_t callback,
-        void * user,
-        int32_t notificationFrames,
-        const sp<IMemory>& sharedBuffer,
-        bool threadCanCallJava,
-        audio_session_t sessionId,
-        transfer_type transferType,
-        const audio_offload_info_t *offloadInfo,
-        const AttributionSourceState& attributionSource,
-        const audio_attributes_t* pAttributes,
-        bool doNotReconnect,
-        float maxRequiredSpeed,
-        audio_port_handle_t selectedDeviceId)
-{
-    if (callback) {
-        mLegacyCallbackWrapper = sp<LegacyCallbackWrapper>::make(callback, user);
-    } else if (user) {
-        LOG_ALWAYS_FATAL("Callback data provided without callback pointer!");
-    }
-    return set(streamType, sampleRate,format, channelMask, frameCount, flags,
-               mLegacyCallbackWrapper, notificationFrames, sharedBuffer, threadCanCallJava,
-               sessionId, transferType, offloadInfo, attributionSource, pAttributes,
-               doNotReconnect, maxRequiredSpeed, selectedDeviceId);
-}
 status_t AudioTrack::set(
         audio_stream_type_t streamType,
         uint32_t sampleRate,
@@ -559,7 +450,7 @@
     std::string errorMessage;
     // 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",
+          "flags %#x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
           __func__,
           streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames,
           sessionId, transferType, attributionSource.uid, attributionSource.pid);
@@ -1357,7 +1248,7 @@
 status_t AudioTrack::getDualMonoMode(audio_dual_mono_mode_t* mode) const
 {
     AutoMutex lock(mLock);
-    media::AudioDualMonoMode mediaMode;
+    media::audio::common::AudioDualMonoMode mediaMode;
     const status_t status = statusTFromBinderStatus(mAudioTrack->getDualMonoMode(&mediaMode));
     if (status == NO_ERROR) {
         *mode = VALUE_OR_RETURN_STATUS(
@@ -1398,6 +1289,10 @@
                         legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(playbackRate))));
         if (status == NO_ERROR) {
             mPlaybackRate = playbackRate;
+        } else if (status == INVALID_OPERATION
+                && playbackRate.mSpeed == 1.0f && mPlaybackRate.mPitch == 1.0f) {
+            mPlaybackRate = playbackRate;
+            return NO_ERROR;
         }
         return status;
     }
@@ -1468,7 +1363,7 @@
 {
     AutoMutex lock(mLock);
     if (isOffloadedOrDirect_l()) {
-        media::AudioPlaybackRate playbackRateTemp;
+        media::audio::common::AudioPlaybackRate playbackRateTemp;
         const status_t status = statusTFromBinderStatus(
                 mAudioTrack->getPlaybackRateParameters(&playbackRateTemp));
         if (status == NO_ERROR) { // update local version if changed.
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index f290453..a005ab4 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -666,17 +666,19 @@
 }
 
 status_t AudioFlingerClientAdapter::getAudioPort(struct audio_port_v7* port) {
-    media::AudioPort portAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_v7_AudioPort(*port));
-    media::AudioPort aidlRet;
+    media::AudioPortFw portAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_v7_AudioPortFw(*port));
+    media::AudioPortFw aidlRet;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mDelegate->getAudioPort(portAidl, &aidlRet)));
-    *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPort_audio_port_v7(aidlRet));
+    *port = VALUE_OR_RETURN_STATUS(aidl2legacy_AudioPortFw_audio_port_v7(aidlRet));
     return OK;
 }
 
 status_t AudioFlingerClientAdapter::createAudioPatch(const struct audio_patch* patch,
                                                      audio_patch_handle_t* handle) {
-    media::AudioPatch patchAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_AudioPatch(*patch));
+    media::AudioPatchFw patchAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_patch_AudioPatchFw(*patch));
     int32_t aidlRet = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_patch_handle_t_int32_t(
                     AUDIO_PATCH_HANDLE_NONE));
     if (handle != nullptr) {
@@ -697,18 +699,18 @@
 
 status_t AudioFlingerClientAdapter::listAudioPatches(unsigned int* num_patches,
                                                      struct audio_patch* patches) {
-    std::vector<media::AudioPatch> aidlRet;
+    std::vector<media::AudioPatchFw> aidlRet;
     int32_t maxPatches = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_patches));
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mDelegate->listAudioPatches(maxPatches, &aidlRet)));
     *num_patches = VALUE_OR_RETURN_STATUS(convertIntegral<unsigned int>(aidlRet.size()));
     return convertRange(aidlRet.begin(), aidlRet.end(), patches,
-                        aidl2legacy_AudioPatch_audio_patch);
+                        aidl2legacy_AudioPatchFw_audio_patch);
 }
 
 status_t AudioFlingerClientAdapter::setAudioPortConfig(const struct audio_port_config* config) {
-    media::AudioPortConfig configAidl = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_port_config_AudioPortConfig(*config));
+    media::AudioPortConfigFw configAidl = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_config_AudioPortConfigFw(*config));
     return statusTFromBinderStatus(mDelegate->setAudioPortConfig(configAidl));
 }
 
@@ -744,14 +746,11 @@
 }
 
 status_t
-AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfo>* microphones) {
-    std::vector<media::MicrophoneInfoData> aidlRet;
-    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
-            mDelegate->getMicrophones(&aidlRet)));
+AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
+    std::vector<media::MicrophoneInfoFw> aidlRet;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getMicrophones(&aidlRet)));
     if (microphones != nullptr) {
-        *microphones = VALUE_OR_RETURN_STATUS(
-                convertContainer<std::vector<media::MicrophoneInfo>>(aidlRet,
-                         media::aidl2legacy_MicrophoneInfo));
+        *microphones = std::move(aidlRet);
     }
     return OK;
 }
@@ -805,16 +804,16 @@
 
 status_t AudioFlingerClientAdapter::setDeviceConnectedState(
         const struct audio_port_v7 *port, bool connected) {
-    media::AudioPort aidlPort = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_port_v7_AudioPort(*port));
+    media::AudioPortFw aidlPort = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_port_v7_AudioPortFw(*port));
     return statusTFromBinderStatus(mDelegate->setDeviceConnectedState(aidlPort, connected));
 }
 
 status_t AudioFlingerClientAdapter::setRequestedLatencyMode(
         audio_io_handle_t output, audio_latency_mode_t mode) {
     int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
-    media::LatencyMode modeAidl  = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_audio_latency_mode_t_LatencyMode(mode));
+    media::audio::common::AudioLatencyMode modeAidl  = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode));
     return statusTFromBinderStatus(mDelegate->setRequestedLatencyMode(outputAidl, modeAidl));
 }
 
@@ -825,14 +824,40 @@
     }
 
     int32_t outputAidl = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
-    std::vector<media::LatencyMode> modesAidl;
+    std::vector<media::audio::common::AudioLatencyMode> modesAidl;
 
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
             mDelegate->getSupportedLatencyModes(outputAidl, &modesAidl)));
 
     *modes = VALUE_OR_RETURN_STATUS(
             convertContainer<std::vector<audio_latency_mode_t>>(modesAidl,
-                     aidl2legacy_LatencyMode_audio_latency_mode_t));
+                     aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
+
+    return NO_ERROR;
+}
+
+status_t AudioFlingerClientAdapter::setBluetoothVariableLatencyEnabled(bool enabled) {
+    return statusTFromBinderStatus(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
+}
+
+status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) {
+    if (enabled == nullptr) {
+        return BAD_VALUE;
+    }
+
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->isBluetoothVariableLatencyEnabled(enabled)));
+
+    return NO_ERROR;
+}
+
+status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) {
+    if (support == nullptr) {
+        return BAD_VALUE;
+    }
+
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mDelegate->supportsBluetoothVariableLatency(support)));
 
     return NO_ERROR;
 }
@@ -1211,17 +1236,17 @@
     return Status::fromStatusT(mDelegate->setLowRamDevice(isLowRamDevice, totalMemory));
 }
 
-Status AudioFlingerServerAdapter::getAudioPort(const media::AudioPort& port,
-                                               media::AudioPort* _aidl_return) {
-    audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPort_audio_port_v7(port));
+Status AudioFlingerServerAdapter::getAudioPort(const media::AudioPortFw& port,
+                                               media::AudioPortFw* _aidl_return) {
+    audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPortFw_audio_port_v7(port));
     RETURN_BINDER_IF_ERROR(mDelegate->getAudioPort(&portLegacy));
-    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPort(portLegacy));
+    *_aidl_return = VALUE_OR_RETURN_BINDER(legacy2aidl_audio_port_v7_AudioPortFw(portLegacy));
     return Status::ok();
 }
 
-Status AudioFlingerServerAdapter::createAudioPatch(const media::AudioPatch& patch,
+Status AudioFlingerServerAdapter::createAudioPatch(const media::AudioPatchFw& patch,
                                                    int32_t* _aidl_return) {
-    audio_patch patchLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPatch_audio_patch(patch));
+    audio_patch patchLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPatchFw_audio_patch(patch));
     audio_patch_handle_t handleLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_patch_handle_t(*_aidl_return));
     RETURN_BINDER_IF_ERROR(mDelegate->createAudioPatch(&patchLegacy, &handleLegacy));
@@ -1236,7 +1261,7 @@
 }
 
 Status AudioFlingerServerAdapter::listAudioPatches(int32_t maxCount,
-                            std::vector<media::AudioPatch>* _aidl_return) {
+                            std::vector<media::AudioPatchFw>* _aidl_return) {
     unsigned int count = VALUE_OR_RETURN_BINDER(convertIntegral<unsigned int>(maxCount));
     count = std::min(count, static_cast<unsigned int>(MAX_ITEMS_PER_LIST));
     std::unique_ptr<audio_patch[]> patchesLegacy(new audio_patch[count]);
@@ -1244,13 +1269,13 @@
     RETURN_BINDER_IF_ERROR(convertRange(&patchesLegacy[0],
                            &patchesLegacy[count],
                            std::back_inserter(*_aidl_return),
-                           legacy2aidl_audio_patch_AudioPatch));
+                           legacy2aidl_audio_patch_AudioPatchFw));
     return Status::ok();
 }
 
-Status AudioFlingerServerAdapter::setAudioPortConfig(const media::AudioPortConfig& config) {
+Status AudioFlingerServerAdapter::setAudioPortConfig(const media::AudioPortConfigFw& config) {
     audio_port_config configLegacy = VALUE_OR_RETURN_BINDER(
-            aidl2legacy_AudioPortConfig_audio_port_config(config));
+            aidl2legacy_AudioPortConfigFw_audio_port_config(config));
     return Status::fromStatusT(mDelegate->setAudioPortConfig(&configLegacy));
 }
 
@@ -1281,11 +1306,8 @@
 }
 
 Status AudioFlingerServerAdapter::getMicrophones(
-        std::vector<media::MicrophoneInfoData>* _aidl_return) {
-    std::vector<media::MicrophoneInfo> resultLegacy;
-    RETURN_BINDER_IF_ERROR(mDelegate->getMicrophones(&resultLegacy));
-    *_aidl_return = VALUE_OR_RETURN_BINDER(convertContainer<std::vector<media::MicrophoneInfoData>>(
-            resultLegacy, media::legacy2aidl_MicrophoneInfo));
+        std::vector<media::MicrophoneInfoFw>* _aidl_return) {
+    RETURN_BINDER_IF_ERROR(mDelegate->getMicrophones(_aidl_return));
     return Status::ok();
 }
 
@@ -1328,23 +1350,23 @@
 }
 
 Status AudioFlingerServerAdapter::setDeviceConnectedState(
-        const media::AudioPort& port, bool connected) {
-    audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPort_audio_port_v7(port));
+        const media::AudioPortFw& port, bool connected) {
+    audio_port_v7 portLegacy = VALUE_OR_RETURN_BINDER(aidl2legacy_AudioPortFw_audio_port_v7(port));
     return Status::fromStatusT(mDelegate->setDeviceConnectedState(&portLegacy, connected));
 }
 
 Status AudioFlingerServerAdapter::setRequestedLatencyMode(
-        int32_t output, media::LatencyMode modeAidl) {
+        int32_t output, media::audio::common::AudioLatencyMode modeAidl) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     audio_latency_mode_t modeLegacy = VALUE_OR_RETURN_BINDER(
-            aidl2legacy_LatencyMode_audio_latency_mode_t(modeAidl));
+            aidl2legacy_AudioLatencyMode_audio_latency_mode_t(modeAidl));
     return Status::fromStatusT(mDelegate->setRequestedLatencyMode(
             outputLegacy, modeLegacy));
 }
 
 Status AudioFlingerServerAdapter::getSupportedLatencyModes(
-        int output, std::vector<media::LatencyMode>* _aidl_return) {
+        int output, std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) {
     audio_io_handle_t outputLegacy = VALUE_OR_RETURN_BINDER(
             aidl2legacy_int32_t_audio_io_handle_t(output));
     std::vector<audio_latency_mode_t> modesLegacy;
@@ -1352,9 +1374,21 @@
     RETURN_BINDER_IF_ERROR(mDelegate->getSupportedLatencyModes(outputLegacy, &modesLegacy));
 
     *_aidl_return = VALUE_OR_RETURN_BINDER(
-            convertContainer<std::vector<media::LatencyMode>>(
-                    modesLegacy, legacy2aidl_audio_latency_mode_t_LatencyMode));
+            convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+                    modesLegacy, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
     return Status::ok();
 }
 
+Status AudioFlingerServerAdapter::setBluetoothVariableLatencyEnabled(bool enabled) {
+    return Status::fromStatusT(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
+}
+
+Status AudioFlingerServerAdapter::isBluetoothVariableLatencyEnabled(bool *enabled) {
+    return Status::fromStatusT(mDelegate->isBluetoothVariableLatencyEnabled(enabled));
+}
+
+Status AudioFlingerServerAdapter::supportsBluetoothVariableLatency(bool *support) {
+    return Status::fromStatusT(mDelegate->supportsBluetoothVariableLatency(support));
+}
+
 } // namespace android
diff --git a/media/libaudioclient/TEST_MAPPING b/media/libaudioclient/TEST_MAPPING
index 3751f80..10f9d9b 100644
--- a/media/libaudioclient/TEST_MAPPING
+++ b/media/libaudioclient/TEST_MAPPING
@@ -4,12 +4,38 @@
       "name": "audio_aidl_conversion_tests"
     },
     {
+      "name": "audio_aidl_status_tests"
+    },
+    {
       "name": "CtsNativeMediaAAudioTestCases",
       "options" : [
         {
           "include-filter": "android.nativemedia.aaudio.AAudioTests#AAudioBasic.*"
         }
       ]
+    },
+    {
+      "name": "audiorecord_tests"
+    },
+    {
+      "name": "audioeffect_tests"
+    },
+    {
+      "name": "audiorouting_tests"
+    },
+    {
+      "name": "audioclient_serialization_tests"
+    },
+    {
+      "name": "trackplayerbase_tests"
+    },
+    {
+      "name": "audiosystem_tests"
+    }
+  ],
+  "postsubmit": [
+    {
+       "name": "audioeffect_analysis"
     }
   ]
 }
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index f968a4b..f0b4d11 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1027,7 +1027,7 @@
     if (property_get("gsm.operator.iso-country", value, "") == 0) {
         property_get("gsm.sim.operator.iso-country", value, "");
     }
-    // If dual sim device has two SIM cards inserted and is not registerd to any network,
+    // If dual sim device has two SIM cards inserted and is not registered to any network,
     // "," is set to "gsm.operator.iso-country" prop.
     // In this case, "gsm.sim.operator.iso-country" prop should be used.
     if (strlen(value) == 1 && strstr(value, ",") != NULL) {
diff --git a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl b/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
deleted file mode 100644
index f6220c2..0000000
--- a/media/libaudioclient/aidl/android/media/AudioDualMonoMode.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.media;
-
-// TODO(b/175167149): Reconcile AudioDualMonoMode with framework-media-sources
-
-@Backing(type="int")
-enum AudioDualMonoMode {
-    OFF = 0,
-    LR = 1,
-    LL = 2,
-    RR = 3,
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl b/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl
new file mode 100644
index 0000000..49048040
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/AudioHalVersion.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * The audio HAL version definition.
+ *
+ * {@hide}
+ */
+parcelable AudioHalVersion {
+
+    @Backing(type="int")
+    enum Type {
+        /**
+         * Indicate the audio HAL is implemented with HIDL (HAL interface definition language).
+         * @see <a href="https://source.android.com/docs/core/architecture/hidl/">HIDL</a>
+         */
+        HIDL = 0,
+
+        /**
+         * Indicate the audio HAL is implemented with AIDL (Android Interface Definition Language).
+         * @see <a href="https://source.android.com/docs/core/architecture/aidl/">AIDL</a>
+         */
+        AIDL
+    }
+
+    Type type = Type.HIDL;
+
+    /**
+     * Major version number.
+     */
+    int major;
+
+    /**
+     * Minor version number.
+     */
+    int minor;
+}
diff --git a/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl b/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl
index b01f902..5dd898c 100644
--- a/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioIoDescriptor.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.AudioPatch;
+import android.media.AudioPatchFw;
 import android.media.audio.common.AudioChannelLayout;
 import android.media.audio.common.AudioFormatDescription;
 
@@ -26,7 +26,7 @@
 parcelable AudioIoDescriptor {
     /** Interpreted as audio_io_handle_t. */
     int ioHandle;
-    AudioPatch patch;
+    AudioPatchFw patch;
     boolean isInput;
     int samplingRate;
     AudioFormatDescription format;
diff --git a/media/libaudioclient/aidl/android/media/AudioPatch.aidl b/media/libaudioclient/aidl/android/media/AudioPatchFw.aidl
similarity index 74%
rename from media/libaudioclient/aidl/android/media/AudioPatch.aidl
rename to media/libaudioclient/aidl/android/media/AudioPatchFw.aidl
index 8519faf..9ec3fa9 100644
--- a/media/libaudioclient/aidl/android/media/AudioPatch.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPatchFw.aidl
@@ -16,17 +16,19 @@
 
 package android.media;
 
-import android.media.AudioPortConfig;
+import android.media.AudioPortConfigFw;
 
 /**
  * {@hide}
+ * The Fw suffix is used to break a namespace collision with an SDK API.
+ * It contains the framework version of AudioPortConfig.
  */
-parcelable AudioPatch {
+parcelable AudioPatchFw {
     /**
      * Patch unique ID.
      * Interpreted as audio_patch_handle_t.
      */
     int id;
-    AudioPortConfig[] sources;
-    AudioPortConfig[] sinks;
+    AudioPortConfigFw[] sources;
+    AudioPortConfigFw[] sinks;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl b/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
deleted file mode 100644
index e29d398..0000000
--- a/media/libaudioclient/aidl/android/media/AudioPlaybackRate.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-/**
- * The AudioPlaybackRate.
- *
- * See https://developer.android.com/reference/android/media/PlaybackParams.
- * TODO(b/175166815): Reconcile with framework-media-sources PlaybackParams.aidl.
- *       As this is used for native wire serialization, no need to define
- *       audio_timestretch_stretch_mode_t and audio_timestretch_fallback_mode_t enums
- *       until we attempt to unify with PlaybackParams.
- *
- * {@hide}
- */
-parcelable AudioPlaybackRate {
-    /** Speed of audio playback, >= 0.f, 1.f nominal (system limits are further restrictive) */
-    float speed;
-    /** Pitch of audio, >= 0.f, 1.f nominal (system limits are further restrictive) */
-    float pitch;
-    /** Interpreted as audio_timestretch_stretch_mode_t */
-    int stretchMode;
-    /** Interpreted as audio_timestretch_fallback_mode_t */
-    int fallbackMode;
-}
diff --git a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl b/media/libaudioclient/aidl/android/media/AudioPortConfigFw.aidl
similarity index 89%
rename from media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
rename to media/libaudioclient/aidl/android/media/AudioPortConfigFw.aidl
index 3a4ca31..e7565d7 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortConfig.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortConfigFw.aidl
@@ -21,8 +21,9 @@
 
 /**
  * {@hide}
+ * Suffixed with Fw to avoid name conflict with SDK class.
  */
-parcelable AudioPortConfig {
+parcelable AudioPortConfigFw {
     AudioPortConfig hal;
     AudioPortConfigSys sys;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl
index 0f5a9b6..24ec230 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortDeviceExtSys.aidl
@@ -22,8 +22,4 @@
 parcelable AudioPortDeviceExtSys {
     /** Module the device is attached to. Interpreted as audio_module_handle_t. */
     int hwModule;
-    /** Bitmask, indexed by AudioEncapsulationMode. */
-    int encapsulationModes;
-    /** Bitmask, indexed by AudioEncapsulationMetadataType. */
-    int encapsulationMetadataTypes;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
index 2cdf4f6..d9c6df4 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortExtSys.aidl
@@ -31,4 +31,6 @@
     AudioPortDeviceExtSys device;
     /** System-only parameters when the port is an audio mix. */
     AudioPortMixExtSys mix;
+    /** Framework audio session identifier. */
+    int session;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPort.aidl b/media/libaudioclient/aidl/android/media/AudioPortFw.aidl
similarity index 88%
rename from media/libaudioclient/aidl/android/media/AudioPort.aidl
rename to media/libaudioclient/aidl/android/media/AudioPortFw.aidl
index ff177c0..5580e35 100644
--- a/media/libaudioclient/aidl/android/media/AudioPort.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortFw.aidl
@@ -21,8 +21,9 @@
 
 /**
  * {@hide}
+ * The Fw suffix is used to break a namespace collision with an SDK API.
  */
-parcelable AudioPort {
+parcelable AudioPortFw {
     AudioPort hal;
     AudioPortSys sys;
 }
diff --git a/media/libaudioclient/aidl/android/media/AudioPortSys.aidl b/media/libaudioclient/aidl/android/media/AudioPortSys.aidl
index f3b5c19..756c469 100644
--- a/media/libaudioclient/aidl/android/media/AudioPortSys.aidl
+++ b/media/libaudioclient/aidl/android/media/AudioPortSys.aidl
@@ -17,7 +17,7 @@
 package android.media;
 
 import android.media.AudioGainSys;
-import android.media.AudioPortConfig;
+import android.media.AudioPortConfigFw;
 import android.media.AudioPortExtSys;
 import android.media.AudioPortRole;
 import android.media.AudioPortType;
@@ -36,7 +36,7 @@
     /** System-only parameters for each AudioGain from 'port.gains'. */
     AudioGainSys[] gains;
     /** Current audio port configuration. */
-    AudioPortConfig activeConfig;
+    AudioPortConfigFw activeConfig;
     /** System-only extra parameters for 'port.ext'. */
     AudioPortExtSys ext;
 }
diff --git a/media/libaudioclient/aidl/android/media/EffectConfig.aidl b/media/libaudioclient/aidl/android/media/EffectConfig.aidl
new file mode 100644
index 0000000..5f62b73
--- /dev/null
+++ b/media/libaudioclient/aidl/android/media/EffectConfig.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.media.audio.common.AudioConfigBase;
+
+/**
+ * Describes configuration of an audio effect. Input and output
+ * audio configurations are described separately because the effect
+ * can perform transformations on channel layouts, for example.
+ *
+ * {@hide}
+ */
+parcelable EffectConfig {
+    /** Configuration of the audio input of the effect. */
+    AudioConfigBase inputCfg;
+    /** Configuration of the audio output of the effect. */
+    AudioConfigBase outputCfg;
+    /**
+     * Specifies whether the effect is instantiated on an input stream,
+     * e.g. on the input from a microphone.
+     */
+    boolean isOnInputStream;
+}
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
index a2bb024..f055cc4 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerClient.aidl
@@ -18,7 +18,7 @@
 
 import android.media.AudioIoConfigEvent;
 import android.media.AudioIoDescriptor;
-import android.media.LatencyMode;
+import android.media.audio.common.AudioLatencyMode;
 
 /**
  * A callback interface for AudioFlinger.
@@ -31,7 +31,8 @@
     /**
      * Called when the latency modes supported on a given output stream change.
      * output is the I/O handle of the output stream for which the change is signalled.
-     * latencyModes is the new list of supported latency modes (See LatencyMode.aidl).
+     * latencyModes is the new list of supported latency modes (See AudioLatencyMode.aidl).
      */
-    oneway void onSupportedLatencyModesChanged(int output, in LatencyMode[] latencyModes);
+    oneway void onSupportedLatencyModesChanged(
+            int output, in AudioLatencyMode[] latencyModes);
 }
diff --git a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
index 9b8a843..7c44c74 100644
--- a/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioFlingerService.aidl
@@ -16,9 +16,9 @@
 
 package android.media;
 
-import android.media.AudioPatch;
-import android.media.AudioPort;
-import android.media.AudioPortConfig;
+import android.media.AudioPatchFw;
+import android.media.AudioPortFw;
+import android.media.AudioPortConfigFw;
 import android.media.AudioUniqueIdUse;
 import android.media.AudioVibratorInfo;
 import android.media.CreateEffectRequest;
@@ -35,12 +35,12 @@
 import android.media.IAudioFlingerClient;
 import android.media.IAudioRecord;
 import android.media.IAudioTrack;
-import android.media.LatencyMode;
-import android.media.MicrophoneInfoData;
+import android.media.MicrophoneInfoFw;
 import android.media.RenderPosition;
 import android.media.TrackSecondaryOutputInfo;
 import android.media.audio.common.AudioChannelLayout;
 import android.media.audio.common.AudioFormatDescription;
+import android.media.audio.common.AudioLatencyMode;
 import android.media.audio.common.AudioMMapPolicyInfo;
 import android.media.audio.common.AudioMMapPolicyType;
 import android.media.audio.common.AudioMode;
@@ -182,18 +182,18 @@
     void setLowRamDevice(boolean isLowRamDevice, long totalMemory);
 
     /* Get attributes for a given audio port */
-    AudioPort getAudioPort(in AudioPort port);
+    AudioPortFw getAudioPort(in AudioPortFw port);
 
     /* Create an audio patch between several source and sink ports */
-    int /* audio_patch_handle_t */ createAudioPatch(in AudioPatch patch);
+    int /* audio_patch_handle_t */ createAudioPatch(in AudioPatchFw patch);
 
     /* Release an audio patch */
     void releaseAudioPatch(int /* audio_patch_handle_t */ handle);
 
     /* List existing audio patches */
-    AudioPatch[] listAudioPatches(int maxCount);
+    AudioPatchFw[] listAudioPatches(int maxCount);
     /* Set audio port configuration */
-    void setAudioPortConfig(in AudioPortConfig config);
+    void setAudioPortConfig(in AudioPortConfigFw config);
 
     /* Get the HW synchronization source used for an audio session */
     int /* audio_hw_sync_t */ getAudioHwSyncForSession(int /* audio_session_t */ sessionId);
@@ -208,7 +208,7 @@
     long frameCountHAL(int /* audio_io_handle_t */ ioHandle);
 
     /* List available microphones and their characteristics */
-    MicrophoneInfoData[] getMicrophones();
+    MicrophoneInfoFw[] getMicrophones();
 
     void setAudioHalPids(in int[] /* pid_t[] */ pids);
 
@@ -227,24 +227,44 @@
 
     int getAAudioHardwareBurstMinUsec();
 
-    void setDeviceConnectedState(in AudioPort devicePort, boolean connected);
+    void setDeviceConnectedState(in AudioPortFw devicePort, boolean connected);
 
     /**
-     * Requests a given latency mode (See LatencyMode.aidl) on an output stream.
+     * Requests a given latency mode (See AudioLatencyMode.aidl) on an output stream.
      * This can be used when some use case on a given mixer/stream can only be enabled
      * if a specific latency mode is selected on the audio path below the HAL.
      * For instance spatial audio with head tracking.
      * output is the I/O handle of the output stream for which the request is made.
      * latencyMode is the requested latency mode.
      */
-     void setRequestedLatencyMode(int output, LatencyMode latencyMode);
+     void setRequestedLatencyMode(int output, AudioLatencyMode latencyMode);
 
     /**
      * Queries the list of latency modes (See LatencyMode.aidl) supported by an output stream.
      * output is the I/O handle of the output stream to which the query applies.
      * returns the list of supported latency modes.
      */
-    LatencyMode[] getSupportedLatencyModes(int output);
+    AudioLatencyMode[] getSupportedLatencyModes(int output);
+
+    /**
+     * Requests if the implementation supports controlling the latency modes
+     * over the Bluetooth A2DP or LE Audio links. If it does,
+     * setRequestedLatencyMode() and getSupportedLatencyModes() APIs can also be used
+     * for streams routed to Bluetooth and not just for the spatializer output.
+     */
+     boolean supportsBluetoothVariableLatency();
+
+    /**
+     * Enables or disables the variable Bluetooth latency control mechanism in the
+     * audio framework and the audio HAL. This does not apply to the latency mode control
+     * on the spatializer output as this is a built-in feature.
+     */
+    void setBluetoothVariableLatencyEnabled(boolean enabled);
+
+    /**
+     * Indicates if the variable Bluetooth latency control mechanism is enabled or disabled.
+     */
+    boolean isBluetoothVariableLatencyEnabled();
 
     // When adding a new method, please review and update
     // IAudioFlinger.h AudioFlingerServerAdapter::Delegate::TransactionCode
diff --git a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
index 8ac89a8..ed7e243 100644
--- a/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioPolicyService.aidl
@@ -23,12 +23,12 @@
 import android.media.AudioDirectMode;
 import android.media.AudioMix;
 import android.media.AudioOffloadMode;
-import android.media.AudioPatch;
+import android.media.AudioPatchFw;
 import android.media.AudioPolicyDeviceState;
 import android.media.AudioPolicyForcedConfig;
 import android.media.AudioPolicyForceUse;
-import android.media.AudioPort;
-import android.media.AudioPortConfig;
+import android.media.AudioPortFw;
+import android.media.AudioPortConfigFw;
 import android.media.AudioPortRole;
 import android.media.AudioPortType;
 import android.media.AudioProductStrategy;
@@ -212,16 +212,16 @@
     int listAudioPorts(AudioPortRole role,
                        AudioPortType type,
                        inout Int count,
-                       out AudioPort[] ports);
+                       out AudioPortFw[] ports);
 
     /** Get attributes for the audio port with the given id (AudioPort.hal.id field). */
-    AudioPort getAudioPort(int /* audio_port_handle_t */ portId);
+    AudioPortFw getAudioPort(int /* audio_port_handle_t */ portId);
 
     /**
      * Create an audio patch between several source and sink ports.
      * The handle argument is used when updating an existing patch.
      */
-    int /* audio_patch_handle_t */ createAudioPatch(in AudioPatch patch, int handle);
+    int /* audio_patch_handle_t */ createAudioPatch(in AudioPatchFw patch, int handle);
 
     /** Release an audio patch. */
     void releaseAudioPatch(int /* audio_patch_handle_t */ handle);
@@ -234,10 +234,10 @@
      * Passing '0' on input and inspecting the value on output is a common way of determining the
      * number of elements without actually retrieving them.
      */
-    int listAudioPatches(inout Int count, out AudioPatch[] patches);
+    int listAudioPatches(inout Int count, out AudioPatchFw[] patches);
 
     /** Set audio port configuration. */
-    void setAudioPortConfig(in AudioPortConfig config);
+    void setAudioPortConfig(in AudioPortConfigFw config);
 
     void registerClient(IAudioPolicyServiceClient client);
 
@@ -261,7 +261,7 @@
 
     void removeUserIdDeviceAffinities(int userId);
 
-    int /* audio_port_handle_t */ startAudioSource(in AudioPortConfig source,
+    int /* audio_port_handle_t */ startAudioSource(in AudioPortConfigFw source,
                                                    in AudioAttributesInternal attributes);
 
     void stopAudioSource(int /* audio_port_handle_t */ portId);
diff --git a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
index 44ef80b..1ea4156 100644
--- a/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioRecord.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.MicrophoneInfoData;
+import android.media.MicrophoneInfoFw;
 
 /**
  * Native code must specify namespace media (media::IAudioRecord) when referring to this class.
@@ -39,7 +39,7 @@
 
   /* Get a list of current active microphones.
    */
-  void getActiveMicrophones(out MicrophoneInfoData[] activeMicrophones);
+  void getActiveMicrophones(out MicrophoneInfoFw[] activeMicrophones);
 
   /* Set the microphone direction (for processing).
    */
diff --git a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
index ac58925..c3a2dbe 100644
--- a/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
+++ b/media/libaudioclient/aidl/android/media/IAudioTrack.aidl
@@ -16,13 +16,13 @@
 
 package android.media;
 
-import android.media.AudioDualMonoMode;
-import android.media.AudioPlaybackRate;
 import android.media.AudioTimestampInternal;
 import android.media.SharedFileRegion;
 import android.media.VolumeShaperConfiguration;
 import android.media.VolumeShaperOperation;
 import android.media.VolumeShaperState;
+import android.media.audio.common.AudioDualMonoMode;
+import android.media.audio.common.AudioPlaybackRate;
 
 /**
  * Unless otherwise noted, methods returning int expect it to be interpreted as a status_t.
diff --git a/media/libaudioclient/aidl/android/media/IEffect.aidl b/media/libaudioclient/aidl/android/media/IEffect.aidl
index 6ec0405..b7f70a6 100644
--- a/media/libaudioclient/aidl/android/media/IEffect.aidl
+++ b/media/libaudioclient/aidl/android/media/IEffect.aidl
@@ -16,6 +16,7 @@
 
 package android.media;
 
+import android.media.EffectConfig;
 import android.media.SharedFileRegion;
 
 /**
@@ -63,6 +64,14 @@
      */
     SharedFileRegion getCblk();
 
+    /**
+     * Provides audio configurations for effect's input and output,
+     * see EffectConfig parcelable for more details.
+     *
+     * @return a status_t code.
+     */
+    int getConfig(out EffectConfig config);
+
     // When adding a new method, please review and update
     // Effects.cpp AudioFlinger::EffectHandle::onTransact()
     // Effects.cpp IEFFECT_BINDER_METHOD_MACRO_LIST
diff --git a/media/libaudioclient/aidl/android/media/LatencyMode.aidl b/media/libaudioclient/aidl/android/media/LatencyMode.aidl
deleted file mode 100644
index 0b2a72b..0000000
--- a/media/libaudioclient/aidl/android/media/LatencyMode.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 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;
-
-/**
- * The latency mode currently used by the spatializer mixer.
- * {@hide}
- */
-@Backing(type="byte")
-enum LatencyMode {
-    /** No specific constraint on the latency */
-    FREE = 0,
-    /** A relatively low latency compatible with head tracking operation (e.g less than 100ms) */
-    LOW = 1,
-}
diff --git a/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl b/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
index 90e7ea6..ddda8bb 100644
--- a/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
+++ b/media/libaudioclient/aidl/android/media/OpenOutputRequest.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.AudioPort;
+import android.media.AudioPortFw;
 import android.media.audio.common.AudioConfig;
 import android.media.audio.common.AudioConfigBase;
 
@@ -29,7 +29,7 @@
     AudioConfig halConfig;
     AudioConfigBase mixerConfig;
     /** Type must be DEVICE. */
-    AudioPort device;
+    AudioPortFw device;
     /** Bitmask, indexed by AudioOutputFlag. */
     int flags;
 }
diff --git a/media/libaudioclient/fuzzer/Android.bp b/media/libaudioclient/fuzzer/Android.bp
index 969e3e6..b1feb60 100644
--- a/media/libaudioclient/fuzzer/Android.bp
+++ b/media/libaudioclient/fuzzer/Android.bp
@@ -25,6 +25,9 @@
 
 cc_fuzz {
     name: "audioflinger_fuzzer",
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
     srcs: [
         "audioflinger_fuzzer.cpp",
     ],
@@ -46,7 +49,6 @@
     ],
     shared_libs: [
         "android.hardware.audio.common-util",
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
         "audiopolicy-aidl-cpp",
@@ -54,6 +56,7 @@
         "av-types-aidl-cpp",
         "capture_state_listener-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
         "libaudioflinger",
         "libaudiofoundation",
         "libaudiomanager",
diff --git a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
index 036e72e..d881447 100644
--- a/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
+++ b/media/libaudioclient/fuzzer/audioflinger_fuzzer.cpp
@@ -359,7 +359,7 @@
     record->getInputFramesLost();
     record->getFlags();
 
-    std::vector<media::MicrophoneInfo> activeMicrophones;
+    std::vector<media::MicrophoneInfoFw> activeMicrophones;
     record->getActiveMicrophones(&activeMicrophones);
     record->releaseBuffer(&audioBuffer);
 
@@ -541,7 +541,7 @@
     AudioSystem::getPrimaryOutputFrameCount();
     AudioSystem::setLowRamDevice(mFdp.ConsumeBool(), mFdp.ConsumeIntegral<int64_t>());
 
-    std::vector<media::MicrophoneInfo> microphones;
+    std::vector<media::MicrophoneInfoFw> microphones;
     AudioSystem::getMicrophones(&microphones);
 
     std::vector<pid_t> pids;
diff --git a/media/libaudioclient/include/media/AidlConversion.h b/media/libaudioclient/include/media/AidlConversion.h
index 1e66164..5bd0114 100644
--- a/media/libaudioclient/include/media/AidlConversion.h
+++ b/media/libaudioclient/include/media/AidlConversion.h
@@ -24,46 +24,21 @@
 #include <android/media/AudioAttributesInternal.h>
 #include <android/media/AudioClient.h>
 #include <android/media/AudioDirectMode.h>
-#include <android/media/AudioDualMonoMode.h>
 #include <android/media/AudioFlag.h>
 #include <android/media/AudioIoConfigEvent.h>
 #include <android/media/AudioIoDescriptor.h>
-#include <android/media/AudioPlaybackRate.h>
-#include <android/media/AudioPort.h>
-#include <android/media/AudioPortConfig.h>
+#include <android/media/AudioPortFw.h>
+#include <android/media/AudioPortConfigFw.h>
 #include <android/media/AudioPortDeviceExtSys.h>
 #include <android/media/AudioTimestampInternal.h>
 #include <android/media/AudioUniqueIdUse.h>
 #include <android/media/EffectDescriptor.h>
-#include <android/media/LatencyMode.h>
+#include <android/media/MicrophoneInfoFw.h>
 #include <android/media/TrackSecondaryOutputInfo.h>
-#include <android/media/audio/common/AudioChannelLayout.h>
-#include <android/media/audio/common/AudioConfig.h>
-#include <android/media/audio/common/AudioConfigBase.h>
-#include <android/media/audio/common/AudioContentType.h>
-#include <android/media/audio/common/AudioDeviceDescription.h>
-#include <android/media/audio/common/AudioEncapsulationMetadataType.h>
-#include <android/media/audio/common/AudioEncapsulationMode.h>
-#include <android/media/audio/common/AudioEncapsulationType.h>
-#include <android/media/audio/common/AudioFormatDescription.h>
-#include <android/media/audio/common/AudioGain.h>
-#include <android/media/audio/common/AudioGainConfig.h>
-#include <android/media/audio/common/AudioGainMode.h>
-#include <android/media/audio/common/AudioInputFlags.h>
-#include <android/media/audio/common/AudioMode.h>
-#include <android/media/audio/common/AudioOffloadInfo.h>
-#include <android/media/audio/common/AudioOutputFlags.h>
-#include <android/media/audio/common/AudioPortExt.h>
-#include <android/media/audio/common/AudioPortMixExt.h>
-#include <android/media/audio/common/AudioProfile.h>
-#include <android/media/audio/common/AudioSource.h>
-#include <android/media/audio/common/AudioStandard.h>
-#include <android/media/audio/common/AudioUsage.h>
-#include <android/media/audio/common/AudioUuid.h>
-#include <android/media/audio/common/ExtraAudioDescriptor.h>
 
 #include <android/media/SharedFileRegion.h>
 #include <binder/IMemory.h>
+#include <media/AidlConversionCppNdk.h>
 #include <media/AidlConversionUtil.h>
 #include <media/AudioClient.h>
 #include <media/AudioCommonTypes.h>
@@ -73,49 +48,6 @@
 
 namespace android {
 
-// maxSize is the size of the C-string buffer (including the 0-terminator), NOT the max length of
-// the string.
-status_t aidl2legacy_string(std::string_view aidl, char* dest, size_t maxSize);
-ConversionResult<std::string> legacy2aidl_string(const char* legacy, size_t maxSize);
-
-ConversionResult<audio_module_handle_t> aidl2legacy_int32_t_audio_module_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_module_handle_t_int32_t(audio_module_handle_t legacy);
-
-ConversionResult<audio_io_handle_t> aidl2legacy_int32_t_audio_io_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_io_handle_t_int32_t(audio_io_handle_t legacy);
-
-ConversionResult<audio_port_handle_t> aidl2legacy_int32_t_audio_port_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_port_handle_t_int32_t(audio_port_handle_t legacy);
-
-ConversionResult<audio_patch_handle_t> aidl2legacy_int32_t_audio_patch_handle_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_patch_handle_t_int32_t(audio_patch_handle_t legacy);
-
-ConversionResult<audio_unique_id_t> aidl2legacy_int32_t_audio_unique_id_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_unique_id_t_int32_t(audio_unique_id_t legacy);
-
-ConversionResult<audio_hw_sync_t> aidl2legacy_int32_t_audio_hw_sync_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_hw_sync_t_int32_t(audio_hw_sync_t legacy);
-
-ConversionResult<unsigned int> aidl2legacy_int32_t_config_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_config_mask_int32_t(unsigned int legacy);
-
-ConversionResult<pid_t> aidl2legacy_int32_t_pid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_pid_t_int32_t(pid_t legacy);
-
-ConversionResult<uid_t> aidl2legacy_int32_t_uid_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_uid_t_int32_t(uid_t legacy);
-
-ConversionResult<String8> aidl2legacy_string_view_String8(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String8_string(const String8& legacy);
-
-ConversionResult<String16> aidl2legacy_string_view_String16(std::string_view aidl);
-ConversionResult<std::string> legacy2aidl_String16_string(const String16& legacy);
-
-ConversionResult<std::optional<String16>>
-aidl2legacy_optional_string_view_optional_String16(std::optional<std::string_view> aidl);
-ConversionResult<std::optional<std::string_view>>
-legacy2aidl_optional_String16_optional_string(std::optional<String16> legacy);
-
 ConversionResult<audio_io_config_event_t> aidl2legacy_AudioIoConfigEvent_audio_io_config_event_t(
         media::AudioIoConfigEvent aidl);
 ConversionResult<media::AudioIoConfigEvent> legacy2aidl_audio_io_config_event_t_AudioIoConfigEvent(
@@ -131,75 +63,6 @@
 ConversionResult<media::AudioPortType> legacy2aidl_audio_port_type_t_AudioPortType(
         audio_port_type_t legacy);
 
-ConversionResult<audio_channel_mask_t> aidl2legacy_AudioChannelLayout_audio_channel_mask_t(
-        const media::audio::common::AudioChannelLayout& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioChannelLayout>
-legacy2aidl_audio_channel_mask_t_AudioChannelLayout(audio_channel_mask_t legacy, bool isInput);
-
-ConversionResult<audio_devices_t> aidl2legacy_AudioDeviceDescription_audio_devices_t(
-        const media::audio::common::AudioDeviceDescription& aidl);
-ConversionResult<media::audio::common::AudioDeviceDescription>
-legacy2aidl_audio_devices_t_AudioDeviceDescription(audio_devices_t legacy);
-
-status_t aidl2legacy_AudioDevice_audio_device(
-        const media::audio::common::AudioDevice& aidl,
-        audio_devices_t* legacyType, char* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
-        const media::audio::common::AudioDevice& aidl,
-        audio_devices_t* legacyType, String8* legacyAddress);
-status_t aidl2legacy_AudioDevice_audio_device(
-        const media::audio::common::AudioDevice& aidl,
-        audio_devices_t* legacyType, std::string* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const char* legacyAddress);
-ConversionResult<media::audio::common::AudioDevice>
-legacy2aidl_audio_device_AudioDevice(
-        audio_devices_t legacyType, const String8& legacyAddress);
-
-ConversionResult<audio_format_t> aidl2legacy_AudioFormatDescription_audio_format_t(
-        const media::audio::common::AudioFormatDescription& aidl);
-ConversionResult<media::audio::common::AudioFormatDescription>
-legacy2aidl_audio_format_t_AudioFormatDescription(audio_format_t legacy);
-
-ConversionResult<audio_gain_mode_t>
-aidl2legacy_AudioGainMode_audio_gain_mode_t(media::audio::common::AudioGainMode aidl);
-ConversionResult<media::audio::common::AudioGainMode>
-legacy2aidl_audio_gain_mode_t_AudioGainMode(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_mode_t> aidl2legacy_int32_t_audio_gain_mode_t_mask(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_gain_mode_t_int32_t_mask(audio_gain_mode_t legacy);
-
-ConversionResult<audio_gain_config> aidl2legacy_AudioGainConfig_audio_gain_config(
-        const media::audio::common::AudioGainConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGainConfig>
-legacy2aidl_audio_gain_config_AudioGainConfig(const audio_gain_config& legacy, bool isInput);
-
-ConversionResult<audio_input_flags_t>
-aidl2legacy_AudioInputFlags_audio_input_flags_t(media::audio::common::AudioInputFlags aidl);
-ConversionResult<media::audio::common::AudioInputFlags>
-legacy2aidl_audio_input_flags_t_AudioInputFlags(audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t>
-aidl2legacy_AudioOutputFlags_audio_output_flags_t(media::audio::common::AudioOutputFlags aidl);
-ConversionResult<media::audio::common::AudioOutputFlags>
-legacy2aidl_audio_output_flags_t_AudioOutputFlags(audio_output_flags_t legacy);
-
-ConversionResult<audio_input_flags_t> aidl2legacy_int32_t_audio_input_flags_t_mask(
-        int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_input_flags_t_int32_t_mask(
-        audio_input_flags_t legacy);
-
-ConversionResult<audio_output_flags_t> aidl2legacy_int32_t_audio_output_flags_t_mask(
-        int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_output_flags_t_int32_t_mask(
-        audio_output_flags_t legacy);
-
-ConversionResult<audio_io_flags> aidl2legacy_AudioIoFlags_audio_io_flags(
-        const media::audio::common::AudioIoFlags& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioIoFlags> legacy2aidl_audio_io_flags_AudioIoFlags(
-        const audio_io_flags& legacy, bool isInput);
-
 ConversionResult<audio_port_config_device_ext>
 aidl2legacy_AudioPortDeviceExt_audio_port_config_device_ext(
         const media::audio::common::AudioPortDeviceExt& aidl,
@@ -214,15 +77,6 @@
 ConversionResult<media::audio::common::AudioStreamType>
 legacy2aidl_audio_stream_type_t_AudioStreamType(audio_stream_type_t legacy);
 
-ConversionResult<audio_source_t> aidl2legacy_AudioSource_audio_source_t(
-        media::audio::common::AudioSource aidl);
-ConversionResult<media::audio::common::AudioSource>
-        legacy2aidl_audio_source_t_AudioSource(
-        audio_source_t legacy);
-
-ConversionResult<audio_session_t> aidl2legacy_int32_t_audio_session_t(int32_t aidl);
-ConversionResult<int32_t> legacy2aidl_audio_session_t_int32_t(audio_session_t legacy);
-
 ConversionResult<audio_port_config_mix_ext> aidl2legacy_AudioPortMixExt(
         const media::audio::common::AudioPortMixExt& aidl, media::AudioPortRole role,
         const media::AudioPortMixExtSys& aidlMixExt);
@@ -235,14 +89,15 @@
 ConversionResult<int32_t> legacy2aidl_audio_port_config_session_ext_AudioPortConfigSessionExt(
         const audio_port_config_session_ext& legacy);
 
-ConversionResult<audio_port_config> aidl2legacy_AudioPortConfig_audio_port_config(
-        const media::AudioPortConfig& aidl);
-ConversionResult<media::AudioPortConfig> legacy2aidl_audio_port_config_AudioPortConfig(
-        const audio_port_config& legacy);
+// portId needs to be set when dealing with the HAL.
+ConversionResult<audio_port_config> aidl2legacy_AudioPortConfigFw_audio_port_config(
+        const media::AudioPortConfigFw& aidl, int32_t* aidlPortId = nullptr);
+ConversionResult<media::AudioPortConfigFw> legacy2aidl_audio_port_config_AudioPortConfigFw(
+        const audio_port_config& legacy, int32_t portId = 0);
 
-ConversionResult<struct audio_patch> aidl2legacy_AudioPatch_audio_patch(
-        const media::AudioPatch& aidl);
-ConversionResult<media::AudioPatch> legacy2aidl_audio_patch_AudioPatch(
+ConversionResult<struct audio_patch> aidl2legacy_AudioPatchFw_audio_patch(
+        const media::AudioPatchFw& aidl);
+ConversionResult<media::AudioPatchFw> legacy2aidl_audio_patch_AudioPatchFw(
         const struct audio_patch& legacy);
 
 ConversionResult<sp<AudioIoDescriptor>> aidl2legacy_AudioIoDescriptor_AudioIoDescriptor(
@@ -255,17 +110,6 @@
 ConversionResult<media::AudioClient> legacy2aidl_AudioClient_AudioClient(
         const AudioClient& legacy);
 
-ConversionResult<audio_content_type_t>
-aidl2legacy_AudioContentType_audio_content_type_t(
-        media::audio::common::AudioContentType aidl);
-ConversionResult<media::audio::common::AudioContentType>
-legacy2aidl_audio_content_type_t_AudioContentType(audio_content_type_t legacy);
-
-ConversionResult<audio_usage_t>
-aidl2legacy_AudioUsage_audio_usage_t(media::audio::common::AudioUsage aidl);
-ConversionResult<media::audio::common::AudioUsage>
-legacy2aidl_audio_usage_t_AudioUsage(audio_usage_t legacy);
-
 ConversionResult<audio_flags_mask_t>
 aidl2legacy_AudioFlag_audio_flags_mask_t(media::AudioFlag aidl);
 ConversionResult<media::AudioFlag>
@@ -281,36 +125,13 @@
 ConversionResult<media::AudioAttributesInternal>
 legacy2aidl_audio_attributes_t_AudioAttributesInternal(const audio_attributes_t& legacy);
 
-ConversionResult<audio_encapsulation_mode_t>
-aidl2legacy_AudioEncapsulationMode_audio_encapsulation_mode_t(
-        media::audio::common::AudioEncapsulationMode aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMode>
-legacy2aidl_audio_encapsulation_mode_t_AudioEncapsulationMode(audio_encapsulation_mode_t legacy);
-
-ConversionResult<audio_offload_info_t>
-aidl2legacy_AudioOffloadInfo_audio_offload_info_t(
-        const media::audio::common::AudioOffloadInfo& aidl);
-ConversionResult<media::audio::common::AudioOffloadInfo>
-legacy2aidl_audio_offload_info_t_AudioOffloadInfo(const audio_offload_info_t& legacy);
-
-ConversionResult<audio_config_t>
-aidl2legacy_AudioConfig_audio_config_t(const media::audio::common::AudioConfig& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfig>
-legacy2aidl_audio_config_t_AudioConfig(const audio_config_t& legacy, bool isInput);
-
-ConversionResult<audio_config_base_t>
-aidl2legacy_AudioConfigBase_audio_config_base_t(
-        const media::audio::common::AudioConfigBase& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioConfigBase>
-legacy2aidl_audio_config_base_t_AudioConfigBase(const audio_config_base_t& legacy, bool isInput);
-
 ConversionResult<sp<IMemory>>
 aidl2legacy_SharedFileRegion_IMemory(const media::SharedFileRegion& aidl);
 ConversionResult<media::SharedFileRegion>
 legacy2aidl_IMemory_SharedFileRegion(const sp<IMemory>& legacy);
 
-ConversionResult<sp<IMemory>>
-aidl2legacy_NullableSharedFileRegion_IMemory(const std::optional<media::SharedFileRegion>& aidl);
+ConversionResult<sp<::android::IMemory>> aidl2legacy_NullableSharedFileRegion_IMemory(
+        const std::optional<media::SharedFileRegion>& aidl);
 ConversionResult<std::optional<media::SharedFileRegion>>
 legacy2aidl_NullableIMemory_SharedFileRegion(const sp<IMemory>& legacy);
 
@@ -319,32 +140,10 @@
 ConversionResult<media::AudioTimestampInternal>
 legacy2aidl_AudioTimestamp_AudioTimestampInternal(const AudioTimestamp& legacy);
 
-ConversionResult<audio_uuid_t>
-aidl2legacy_AudioUuid_audio_uuid_t(const media::audio::common::AudioUuid& aidl);
-ConversionResult<media::audio::common::AudioUuid>
-legacy2aidl_audio_uuid_t_AudioUuid(const audio_uuid_t& legacy);
-
 ConversionResult<effect_descriptor_t>
 aidl2legacy_EffectDescriptor_effect_descriptor_t(const media::EffectDescriptor& aidl);
-ConversionResult<media::EffectDescriptor>
-legacy2aidl_effect_descriptor_t_EffectDescriptor(const effect_descriptor_t& legacy);
-
-ConversionResult<audio_encapsulation_metadata_type_t>
-aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(
-        media::audio::common::AudioEncapsulationMetadataType aidl);
-ConversionResult<media::audio::common::AudioEncapsulationMetadataType>
-legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
-        audio_encapsulation_metadata_type_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMode_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMode_mask(uint32_t legacy);
-
-ConversionResult<uint32_t>
-aidl2legacy_AudioEncapsulationMetadataType_mask(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_AudioEncapsulationMetadataType_mask(uint32_t legacy);
+ConversionResult<media::EffectDescriptor> legacy2aidl_effect_descriptor_t_EffectDescriptor(
+        const effect_descriptor_t& legacy);
 
 ConversionResult<audio_port_device_ext>
 aidl2legacy_AudioPortDeviceExt_audio_port_device_ext(
@@ -369,26 +168,10 @@
 ConversionResult<int32_t>
 legacy2aidl_audio_port_session_ext_int32_t(const audio_port_session_ext& legacy);
 
-ConversionResult<audio_profile>
-aidl2legacy_AudioProfile_audio_profile(
-        const media::audio::common::AudioProfile& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioProfile>
-legacy2aidl_audio_profile_AudioProfile(const audio_profile& legacy, bool isInput);
-
-ConversionResult<audio_gain>
-aidl2legacy_AudioGain_audio_gain(const media::audio::common::AudioGain& aidl, bool isInput);
-ConversionResult<media::audio::common::AudioGain>
-legacy2aidl_audio_gain_AudioGain(const audio_gain& legacy, bool isInput);
-
 ConversionResult<audio_port_v7>
-aidl2legacy_AudioPort_audio_port_v7(const media::AudioPort& aidl);
-ConversionResult<media::AudioPort>
-legacy2aidl_audio_port_v7_AudioPort(const audio_port_v7& legacy);
-
-ConversionResult<audio_mode_t>
-aidl2legacy_AudioMode_audio_mode_t(media::audio::common::AudioMode aidl);
-ConversionResult<media::audio::common::AudioMode>
-legacy2aidl_audio_mode_t_AudioMode(audio_mode_t legacy);
+aidl2legacy_AudioPortFw_audio_port_v7(const media::AudioPortFw& aidl);
+ConversionResult<media::AudioPortFw>
+legacy2aidl_audio_port_v7_AudioPortFw(const audio_port_v7& legacy);
 
 ConversionResult<audio_unique_id_use_t>
 aidl2legacy_AudioUniqueIdUse_audio_unique_id_use_t(media::AudioUniqueIdUse aidl);
@@ -400,45 +183,6 @@
 ConversionResult<int32_t>
 legacy2aidl_volume_group_t_int32_t(volume_group_t legacy);
 
-ConversionResult<audio_dual_mono_mode_t>
-aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(media::AudioDualMonoMode aidl);
-ConversionResult<media::AudioDualMonoMode>
-legacy2aidl_audio_dual_mono_mode_t_AudioDualMonoMode(audio_dual_mono_mode_t legacy);
-
-ConversionResult<audio_timestretch_fallback_mode_t>
-aidl2legacy_int32_t_audio_timestretch_fallback_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_fallback_mode_t_int32_t(audio_timestretch_fallback_mode_t legacy);
-
-ConversionResult<audio_timestretch_stretch_mode_t>
-aidl2legacy_int32_t_audio_timestretch_stretch_mode_t(int32_t aidl);
-ConversionResult<int32_t>
-legacy2aidl_audio_timestretch_stretch_mode_t_int32_t(audio_timestretch_stretch_mode_t legacy);
-
-ConversionResult<audio_playback_rate_t>
-aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(const media::AudioPlaybackRate& aidl);
-ConversionResult<media::AudioPlaybackRate>
-legacy2aidl_audio_playback_rate_t_AudioPlaybackRate(const audio_playback_rate_t& legacy);
-
-ConversionResult<audio_standard_t>
-aidl2legacy_AudioStandard_audio_standard_t(media::audio::common::AudioStandard aidl);
-ConversionResult<media::audio::common::AudioStandard>
-legacy2aidl_audio_standard_t_AudioStandard(audio_standard_t legacy);
-
-ConversionResult<audio_extra_audio_descriptor>
-aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(
-        const media::audio::common::ExtraAudioDescriptor& aidl);
-ConversionResult<media::audio::common::ExtraAudioDescriptor>
-legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(
-        const audio_extra_audio_descriptor& legacy);
-
-ConversionResult<audio_encapsulation_type_t>
-aidl2legacy_AudioEncapsulationType_audio_encapsulation_type_t(
-        const media::audio::common::AudioEncapsulationType& aidl);
-ConversionResult<media::audio::common::AudioEncapsulationType>
-legacy2aidl_audio_encapsulation_type_t_AudioEncapsulationType(
-        const audio_encapsulation_type_t & legacy);
-
 using TrackSecondaryOutputInfoPair = std::pair<audio_port_handle_t, std::vector<audio_io_handle_t>>;
 ConversionResult<TrackSecondaryOutputInfoPair>
 aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(
@@ -455,9 +199,11 @@
 ConversionResult<audio_direct_mode_t> aidl2legacy_int32_t_audio_direct_mode_t_mask(int32_t aidl);
 ConversionResult<int32_t> legacy2aidl_audio_direct_mode_t_int32_t_mask(audio_direct_mode_t legacy);
 
-ConversionResult<audio_latency_mode_t>
-aidl2legacy_LatencyMode_audio_latency_mode_t(media::LatencyMode aidl);
-ConversionResult<media::LatencyMode>
-legacy2aidl_audio_latency_mode_t_LatencyMode(audio_latency_mode_t legacy);
+ConversionResult<audio_microphone_characteristic_t>
+aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(
+        const media::MicrophoneInfoFw& aidl);
+ConversionResult<media::MicrophoneInfoFw>
+legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+        const audio_microphone_characteristic_t& legacy);
 
 }  // namespace android
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index 56884a3..291312e 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -136,7 +136,7 @@
      *                      indicated by count.
      *      PERMISSION_DENIED could not get AudioFlinger interface
      *      NO_INIT         effect library failed to initialize
-     *      BAD_VALUE       invalid audio session or descriptor pointers
+     *      BAD_VALUE       invalid audio session, or invalid descriptor or count pointers
      *
      * Returned value
      *   *descriptor updated with descriptors of pre processings enabled by default
@@ -160,6 +160,7 @@
      *      NO_ERROR        successful operation.
      *      PERMISSION_DENIED could not get AudioFlinger interface
      *                        or caller lacks required permissions.
+     *      BAD_VALUE       invalid pointer to id
      * Returned value
      *   *id:  The new unique system-wide effect id.
      */
@@ -194,7 +195,7 @@
      *      PERMISSION_DENIED could not get AudioFlinger interface
      *                        or caller lacks required permissions.
      *      NO_INIT         effect library failed to initialize.
-     *      BAD_VALUE       invalid source, type uuid or implementation uuid.
+     *      BAD_VALUE       invalid source, type uuid or implementation uuid, or id pointer
      *      NAME_NOT_FOUND  no effect with this uuid or type found.
      *
      * Returned value
@@ -233,7 +234,7 @@
      *      PERMISSION_DENIED could not get AudioFlinger interface
      *                        or caller lacks required permissions.
      *      NO_INIT         effect library failed to initialize.
-     *      BAD_VALUE       invalid type uuid or implementation uuid.
+     *      BAD_VALUE       invalid type uuid or implementation uuid, or id pointer
      *      NAME_NOT_FOUND  no effect with this uuid or type found.
      *
      * Returned value
@@ -517,7 +518,7 @@
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation.
      *  - INVALID_OPERATION: the application does not have control of the effect engine.
-     *  - BAD_VALUE: invalid parameter identifier or value.
+     *  - BAD_VALUE: invalid parameter structure pointer, or invalid identifier or value.
      *  - DEAD_OBJECT: the effect engine has been deleted.
      */
      virtual status_t   setParameter(effect_param_t *param);
@@ -562,7 +563,7 @@
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation.
      *  - INVALID_OPERATION: the AudioEffect was not successfully initialized.
-     *  - BAD_VALUE: invalid parameter identifier.
+     *  - BAD_VALUE: invalid parameter structure pointer, or invalid parameter identifier.
      *  - DEAD_OBJECT: the effect engine has been deleted.
      */
      virtual status_t   getParameter(effect_param_t *param);
@@ -577,6 +578,25 @@
                               uint32_t *replySize,
                               void *replyData);
 
+    /* Retrieves the configuration of the effect.
+     *
+     * Parameters:
+     *      inputCfg:  pointer to audio_config_base_t structure receiving input
+     *          configuration of the effect
+     *      outputCfg: pointer to audio_config_base_t structure receiving output
+     *          configuration of the effect
+     *
+     * Channel masks of the returned configs are "input" or "output" depending
+     * on the direction of the stream that the effect is attached to.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation.
+     *  - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+     *  - BAD_VALUE: null config pointers
+     *  - DEAD_OBJECT: the effect engine has been deleted.
+     */
+     virtual status_t   getConfigs(audio_config_base_t *inputCfg,
+                                   audio_config_base_t *outputCfg);
 
      /*
       * Utility functions.
@@ -628,7 +648,7 @@
     {
     public:
 
-        EffectClient(AudioEffect *effect) : mEffect(effect){}
+        explicit EffectClient(const sp<AudioEffect>& effect) : mEffect(effect){}
 
         // IEffectClient
         binder::Status controlStatusChanged(bool controlGranted) override {
diff --git a/media/libaudioclient/include/media/AudioPolicy.h b/media/libaudioclient/include/media/AudioPolicy.h
index fbb1100..cab476e 100644
--- a/media/libaudioclient/include/media/AudioPolicy.h
+++ b/media/libaudioclient/include/media/AudioPolicy.h
@@ -72,6 +72,7 @@
     status_t readFromParcel(Parcel *parcel);
     status_t writeToParcel(Parcel *parcel) const;
 
+    bool isExcludeCriterion() const;
     union {
         audio_usage_t   mUsage;
         audio_source_t  mSource;
@@ -88,23 +89,24 @@
     static const uint32_t kCbFlagNotifyActivity = 0x1;
 
     AudioMix() {}
-    AudioMix(Vector<AudioMixMatchCriterion> criteria, uint32_t mixType, audio_config_t format,
-             uint32_t routeFlags, String8 registrationId, uint32_t flags) :
+    AudioMix(const std::vector<AudioMixMatchCriterion> &criteria, uint32_t mixType,
+             audio_config_t format, uint32_t routeFlags,const String8 &registrationId,
+             uint32_t flags) :
         mCriteria(criteria), mMixType(mixType), mFormat(format),
         mRouteFlags(routeFlags), mDeviceAddress(registrationId), mCbFlags(flags){}
 
     status_t readFromParcel(Parcel *parcel);
     status_t writeToParcel(Parcel *parcel) const;
 
-    void setExcludeUid(uid_t uid) const;
-    void setMatchUid(uid_t uid) const;
+    void setExcludeUid(uid_t uid);
+    void setMatchUid(uid_t uid);
     /** returns true if this mix has a rule to match or exclude the given uid */
     bool hasUidRule(bool match, uid_t uid) const;
     /** returns true if this mix has a rule for uid match (any uid) */
     bool hasMatchUidRule() const;
 
-    void setExcludeUserId(int userId) const;
-    void setMatchUserId(int userId) const;
+    void setExcludeUserId(int userId);
+    void setMatchUserId(int userId);
     /** returns true if this mix has a rule to match or exclude the given userId */
     bool hasUserIdRule(bool match, int userId) const;
     /** returns true if this mix has a rule for userId match (any userId) */
@@ -112,7 +114,7 @@
     /** returns true if this mix can be used for uid-device affinity routing */
     bool isDeviceAffinityCompatible() const;
 
-    mutable Vector<AudioMixMatchCriterion> mCriteria;
+    std::vector<AudioMixMatchCriterion> mCriteria;
     uint32_t        mMixType;
     audio_config_t  mFormat;
     uint32_t        mRouteFlags;
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index cb05dd9..ae70a7f 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -26,7 +26,6 @@
 #include <media/AudioTimestamp.h>
 #include <media/MediaMetricsItem.h>
 #include <media/Modulo.h>
-#include <media/MicrophoneInfo.h>
 #include <media/RecordingActivityTracker.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
@@ -46,27 +45,6 @@
 {
 public:
 
-    /* Events used by AudioRecord callback function (legacy_callback_t).
-     * Keep in sync with frameworks/base/media/java/android/media/AudioRecord.java NATIVE_EVENT_*.
-     */
-    enum event_type {
-        EVENT_MORE_DATA = 0,        // Request to read available data from buffer.
-                                    // If this event is delivered but the callback handler
-                                    // does not want to read the available data, the handler must
-                                    // explicitly ignore the event by setting frameCount to zero.
-        EVENT_OVERRUN = 1,          // Buffer overrun occurred.
-        EVENT_MARKER = 2,           // Record head is at the specified marker position
-                                    // (See setMarkerPosition()).
-        EVENT_NEW_POS = 3,          // Record head is at a new position
-                                    // (See setPositionUpdatePeriod()).
-        EVENT_NEW_IAUDIORECORD = 4, // IAudioRecord was re-created, either due to re-routing and
-                                    // voluntary invalidation by mediaserver, or mediaserver crash.
-    };
-
-    /* Client should declare a Buffer and pass address to obtainBuffer()
-     * and releaseBuffer().  See also legacy_callback_t for EVENT_MORE_DATA.
-     */
-
     class Buffer
     {
       friend AudioRecord;
@@ -122,7 +100,6 @@
      *          - EVENT_NEW_IAUDIORECORD: unused.
      */
 
-    typedef void (*legacy_callback_t)(int event, void* user, void *info);
 
     class IAudioRecordCallback : public virtual RefBase {
         friend AudioRecord;
@@ -226,24 +203,6 @@
                                     float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT);
 
 
-                        AudioRecord(audio_source_t inputSource,
-                                    uint32_t sampleRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    const android::content::AttributionSourceState& client,
-                                    size_t frameCount,
-                                    legacy_callback_t callback,
-                                    void* user,
-                                    uint32_t notificationFrames = 0,
-                                    audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
-                                    transfer_type transferType = TRANSFER_DEFAULT,
-                                    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
-                                    const audio_attributes_t* pAttributes = nullptr,
-                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
-                                    audio_microphone_direction_t
-                                        selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
-                                    float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT);
-
     /* Terminates the AudioRecord and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioRecord.
      */
@@ -286,27 +245,6 @@
                             float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT,
                             int32_t maxSharedAudioHistoryMs = 0);
 
-           status_t    set(audio_source_t inputSource,
-                            uint32_t sampleRate,
-                            audio_format_t format,
-                            audio_channel_mask_t channelMask,
-                            size_t frameCount,
-                            legacy_callback_t callback,
-                            void* user,
-                            uint32_t notificationFrames = 0,
-                            bool threadCanCallJava = false,
-                            audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
-                            transfer_type transferType = TRANSFER_DEFAULT,
-                            audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
-                            uid_t uid = AUDIO_UID_INVALID,
-                            pid_t pid = -1,
-                            const audio_attributes_t* pAttributes = nullptr,
-                            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
-                            audio_microphone_direction_t
-                                selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
-                            float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT,
-                            int32_t maxSharedAudioHistoryMs = 0);
-
     /* Result of constructing the AudioRecord. This must be checked for successful initialization
      * before using any AudioRecord API (except for set()), because using
      * an uninitialized AudioRecord produces undefined results.
@@ -636,10 +574,11 @@
     /* Get the flags */
             audio_input_flags_t getFlags() const { AutoMutex _l(mLock); return mFlags; }
 
-    /* Get active microphones. A empty vector of MicrophoneInfo will be passed as a parameter,
+    /* Get active microphones. A empty vector of MicrophoneInfoFw will be passed as a parameter,
      * the data will be filled when querying the hal.
      */
-            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+            status_t    getActiveMicrophones(
+                    std::vector<media::MicrophoneInfoFw>* activeMicrophones);
 
     /* Set the Microphone direction (for processing purposes).
      */
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 9411f46..543ce00 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -28,6 +28,7 @@
 #include <android/media/BnAudioPolicyServiceClient.h>
 #include <android/media/INativeSpatializerCallback.h>
 #include <android/media/ISpatializer.h>
+#include <android/media/MicrophoneInfoFw.h>
 #include <android/media/audio/common/AudioMMapPolicyInfo.h>
 #include <android/media/audio/common/AudioMMapPolicyType.h>
 #include <android/media/audio/common/AudioPort.h>
@@ -38,7 +39,6 @@
 #include <media/AudioProductStrategy.h>
 #include <media/AudioVolumeGroup.h>
 #include <media/AudioIoDescriptor.h>
-#include <media/MicrophoneInfo.h>
 #include <system/audio.h>
 #include <system/audio_effect.h>
 #include <system/audio_policy.h>
@@ -428,7 +428,7 @@
     static float    getStreamVolumeDB(
             audio_stream_type_t stream, int index, audio_devices_t device);
 
-    static status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+    static status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
 
     static status_t getHwOffloadFormatsSupportedForBluetoothMedia(
                                     audio_devices_t device, std::vector<audio_format_t> *formats);
@@ -575,6 +575,12 @@
     static status_t getSupportedLatencyModes(audio_io_handle_t output,
             std::vector<audio_latency_mode_t>* modes);
 
+    static status_t setBluetoothVariableLatencyEnabled(bool enabled);
+
+    static status_t isBluetoothVariableLatencyEnabled(bool *enabled);
+
+    static status_t supportsBluetoothVariableLatency(bool *support);
+
     // A listener for capture state changes.
     class CaptureStateListener : public virtual RefBase {
     public:
@@ -705,7 +711,8 @@
                 const media::AudioIoDescriptor& ioDesc) override;
 
         binder::Status onSupportedLatencyModesChanged(
-                int output, const std::vector<media::LatencyMode>& latencyModes) override;
+                int output,
+                const std::vector<media::audio::common::AudioLatencyMode>& latencyModes) override;
 
         status_t addAudioDeviceCallback(const wp<AudioDeviceCallback>& callback,
                                                audio_io_handle_t audioIo,
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 9f540e6..b6ee483 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -148,7 +148,6 @@
      *          - EVENT_NEW_TIMESTAMP: pointer to const AudioTimestamp.
      */
 
-    typedef void (*legacy_callback_t)(int event, void* user, void* info);
     class IAudioTrackCallback : public virtual RefBase {
       friend AudioTrack;
       protected:
@@ -343,26 +342,6 @@
                                     float maxRequiredSpeed = 1.0f,
                                     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
 
-
-                        AudioTrack( audio_stream_type_t streamType,
-                                    uint32_t sampleRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    size_t frameCount,
-                                    audio_output_flags_t flags,
-                                    legacy_callback_t cbf,
-                                    void* user = nullptr,
-                                    int32_t notificationFrames = 0,
-                                    audio_session_t sessionId  = AUDIO_SESSION_ALLOCATE,
-                                    transfer_type transferType = TRANSFER_DEFAULT,
-                                    const audio_offload_info_t *offloadInfo = nullptr,
-                                    const AttributionSourceState& attributionSource =
-                                        AttributionSourceState(),
-                                    const audio_attributes_t* pAttributes = nullptr,
-                                    bool doNotReconnect = false,
-                                    float maxRequiredSpeed = 1.0f,
-                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
-
     /* Creates an audio track and registers it with AudioFlinger.
      * With this constructor, the track is configured for static buffer mode.
      * Data to be rendered is passed in a shared memory buffer
@@ -391,25 +370,6 @@
                                     bool doNotReconnect = false,
                                     float maxRequiredSpeed = 1.0f);
 
-
-                        AudioTrack( audio_stream_type_t streamType,
-                                    uint32_t sampleRate,
-                                    audio_format_t format,
-                                    audio_channel_mask_t channelMask,
-                                    const sp<IMemory>& sharedBuffer,
-                                    audio_output_flags_t flags,
-                                    legacy_callback_t cbf,
-                                    void* user          = nullptr,
-                                    int32_t notificationFrames = 0,
-                                    audio_session_t sessionId   = AUDIO_SESSION_ALLOCATE,
-                                    transfer_type transferType = TRANSFER_DEFAULT,
-                                    const audio_offload_info_t *offloadInfo = nullptr,
-                                    const AttributionSourceState& attributionSource =
-                                        AttributionSourceState(),
-                                    const audio_attributes_t* pAttributes = nullptr,
-                                    bool doNotReconnect = false,
-                                    float maxRequiredSpeed = 1.0f);
-
     /* Terminates the AudioTrack and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioTrack.
      */
@@ -490,28 +450,8 @@
                         }
             void       onFirstRef() override;
         public:
-            status_t    set(audio_stream_type_t streamType,
-                            uint32_t sampleRate,
-                            audio_format_t format,
-                            audio_channel_mask_t channelMask,
-                            size_t frameCount,
-                            audio_output_flags_t flags,
-                            legacy_callback_t callback,
-                            void * user = nullptr,
-                            int32_t notificationFrames = 0,
-                            const sp<IMemory>& sharedBuffer = 0,
-                            bool threadCanCallJava = false,
-                            audio_session_t sessionId  = AUDIO_SESSION_ALLOCATE,
-                            transfer_type transferType = TRANSFER_DEFAULT,
-                            const audio_offload_info_t *offloadInfo = nullptr,
-                            const AttributionSourceState& attributionSource =
-                                AttributionSourceState(),
-                            const audio_attributes_t* pAttributes = nullptr,
-                            bool doNotReconnect = false,
-                            float maxRequiredSpeed = 1.0f,
-                            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
-
-    // FIXME(b/169889714): Vendor code depends on the old method signature at link time
+            typedef void (*legacy_callback_t)(int event, void* user, void* info);
+            // FIXME(b/169889714): Vendor code depends on the old method signature at link time
             status_t    set(audio_stream_type_t streamType,
                             uint32_t sampleRate,
                             audio_format_t format,
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index c891ae6..25b5414 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -32,7 +32,6 @@
 #include <system/audio_effect.h>
 #include <system/audio_policy.h>
 #include <utils/String8.h>
-#include <media/MicrophoneInfo.h>
 #include <map>
 #include <string>
 #include <vector>
@@ -339,7 +338,7 @@
     virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
 
     /* List available microphones and their characteristics */
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+    virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
 
     virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
 
@@ -367,6 +366,11 @@
     virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
             std::vector<audio_latency_mode_t>* modes) = 0;
 
+    virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
+
+    virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
+
+    virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
 };
 
 /**
@@ -458,7 +462,7 @@
     status_t audioPolicyReady() override;
 
     size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
-    status_t getMicrophones(std::vector<media::MicrophoneInfo>* microphones) override;
+    status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) override;
     status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
     status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
     status_t updateSecondaryOutputs(
@@ -473,6 +477,9 @@
             audio_latency_mode_t mode) override;
     status_t getSupportedLatencyModes(
             audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
+    status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
+    status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
+    status_t supportsBluetoothVariableLatency(bool* support) override;
 
 private:
     const sp<media::IAudioFlingerService> mDelegate;
@@ -564,6 +571,12 @@
             SET_DEVICE_CONNECTED_STATE = media::BnAudioFlingerService::TRANSACTION_setDeviceConnectedState,
             SET_REQUESTED_LATENCY_MODE = media::BnAudioFlingerService::TRANSACTION_setRequestedLatencyMode,
             GET_SUPPORTED_LATENCY_MODES = media::BnAudioFlingerService::TRANSACTION_getSupportedLatencyModes,
+            SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
+                    media::BnAudioFlingerService::TRANSACTION_setBluetoothVariableLatencyEnabled,
+            IS_BLUETOOTH_VARIABLE_LATENCY_ENABLED =
+                    media::BnAudioFlingerService::TRANSACTION_isBluetoothVariableLatencyEnabled,
+            SUPPORTS_BLUETOOTH_VARIABLE_LATENCY =
+                    media::BnAudioFlingerService::TRANSACTION_supportsBluetoothVariableLatency,
         };
 
     protected:
@@ -664,17 +677,17 @@
     Status getPrimaryOutputSamplingRate(int32_t* _aidl_return) override;
     Status getPrimaryOutputFrameCount(int64_t* _aidl_return) override;
     Status setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
-    Status getAudioPort(const media::AudioPort& port, media::AudioPort* _aidl_return) override;
-    Status createAudioPatch(const media::AudioPatch& patch, int32_t* _aidl_return) override;
+    Status getAudioPort(const media::AudioPortFw& port, media::AudioPortFw* _aidl_return) override;
+    Status createAudioPatch(const media::AudioPatchFw& patch, int32_t* _aidl_return) override;
     Status releaseAudioPatch(int32_t handle) override;
     Status listAudioPatches(int32_t maxCount,
-                            std::vector<media::AudioPatch>* _aidl_return) override;
-    Status setAudioPortConfig(const media::AudioPortConfig& config) override;
+                            std::vector<media::AudioPatchFw>* _aidl_return) override;
+    Status setAudioPortConfig(const media::AudioPortConfigFw& config) override;
     Status getAudioHwSyncForSession(int32_t sessionId, int32_t* _aidl_return) override;
     Status systemReady() override;
     Status audioPolicyReady() override;
     Status frameCountHAL(int32_t ioHandle, int64_t* _aidl_return) override;
-    Status getMicrophones(std::vector<media::MicrophoneInfoData>* _aidl_return) override;
+    Status getMicrophones(std::vector<media::MicrophoneInfoFw>* _aidl_return) override;
     Status setAudioHalPids(const std::vector<int32_t>& pids) override;
     Status setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
     Status updateSecondaryOutputs(
@@ -684,10 +697,14 @@
             std::vector<media::audio::common::AudioMMapPolicyInfo> *_aidl_return) override;
     Status getAAudioMixerBurstCount(int32_t* _aidl_return) override;
     Status getAAudioHardwareBurstMinUsec(int32_t* _aidl_return) override;
-    Status setDeviceConnectedState(const media::AudioPort& port, bool connected) override;
-    Status setRequestedLatencyMode(int output, media::LatencyMode mode) override;
+    Status setDeviceConnectedState(const media::AudioPortFw& port, bool connected) override;
+    Status setRequestedLatencyMode(
+            int output, media::audio::common::AudioLatencyMode mode) override;
     Status getSupportedLatencyModes(int output,
-            std::vector<media::LatencyMode>* _aidl_return) override;
+            std::vector<media::audio::common::AudioLatencyMode>* _aidl_return) override;
+    Status setBluetoothVariableLatencyEnabled(bool enabled) override;
+    Status isBluetoothVariableLatencyEnabled(bool* enabled) override;
+    Status supportsBluetoothVariableLatency(bool* support) override;
 private:
     const sp<AudioFlingerServerAdapter::Delegate> mDelegate;
 };
diff --git a/media/libaudioclient/tests/Android.bp b/media/libaudioclient/tests/Android.bp
index 891293e..2189521 100644
--- a/media/libaudioclient/tests/Android.bp
+++ b/media/libaudioclient/tests/Android.bp
@@ -24,7 +24,10 @@
 
 cc_test {
     name: "audio_aidl_conversion_tests",
-    defaults: ["libaudioclient_tests_defaults"],
+    defaults: [
+        "libaudioclient_tests_defaults",
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     srcs: ["audio_aidl_legacy_conversion_tests.cpp"],
     shared_libs: [
         "libbinder",
@@ -33,9 +36,10 @@
         "libutils",
     ],
     static_libs: [
-        "android.media.audio.common.types-V1-cpp",
-        "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
+        "audioclient-types-aidl-cpp",
+        "av-types-aidl-cpp",
         "libstagefright_foundation",
     ],
 }
@@ -93,3 +97,132 @@
     ],
     data: ["record_test_input_*.txt"],
 }
+
+cc_defaults {
+    name: "libaudioclient_gtests_defaults",
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
+    shared_libs: [
+        "capture_state_listener-aidl-cpp",
+        "framework-permission-aidl-cpp",
+        "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
+        "libbase",
+        "libbinder",
+        "libcgrouprc",
+        "libcutils",
+        "libdl",
+        "liblog",
+        "libmedia",
+        "libmediametrics",
+        "libmediautils",
+        "libmedia_helper",
+        "libnblog",
+        "libprocessgroup",
+        "libshmemcompat",
+        "libstagefright_foundation",
+        "libutils",
+        "libxml2",
+        "mediametricsservice-aidl-cpp",
+        "packagemanager_aidl-cpp",
+        "shared-file-region-aidl-cpp",
+    ],
+    static_libs: [
+        "android.hardware.audio.common@7.0-enums",
+        "audioclient-types-aidl-cpp",
+        "audioflinger-aidl-cpp",
+        "audiopolicy-aidl-cpp",
+        "audiopolicy-types-aidl-cpp",
+        "av-types-aidl-cpp",
+        "effect-aidl-cpp",
+        "libaudioclient",
+        "libaudiofoundation",
+        "libaudiomanager",
+        "libaudiopolicy",
+        "libaudioutils",
+    ],
+    data: ["bbb*.raw"],
+    test_config_template: "audio_test_template.xml",
+    test_suites: ["device-tests"],
+}
+
+cc_test {
+    name: "audiorecord_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: [
+        "audiorecord_tests.cpp",
+        "audio_test_utils.cpp",
+    ],
+}
+
+cc_test {
+    name: "audiotrack_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: [
+        "audiotrack_tests.cpp",
+        "audio_test_utils.cpp",
+    ],
+}
+
+cc_test {
+    name: "audioeffect_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: [
+        "audioeffect_tests.cpp",
+        "audio_test_utils.cpp",
+    ],
+}
+
+cc_test {
+    name: "audioeffect_analysis",
+    defaults: ["libaudioclient_gtests_defaults"],
+    // flag needed for pfft/pffft.hpp
+    cflags: [
+        "-Wno-error=unused-parameter",
+    ],
+    srcs: [
+        "audioeffect_analyser.cpp",
+        "audio_test_utils.cpp",
+    ],
+    static_libs: [
+        "libpffft",
+    ],
+}
+
+cc_test {
+    name: "audiorouting_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: [
+        "audiorouting_tests.cpp",
+        "audio_test_utils.cpp",
+    ],
+}
+
+cc_test {
+    name: "audioclient_serialization_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: [
+        "audioclient_serialization_tests.cpp",
+        "audio_test_utils.cpp",
+    ],
+}
+
+cc_test {
+    name: "trackplayerbase_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: ["trackplayerbase_tests.cpp"],
+}
+
+cc_test {
+    name: "audiosystem_tests",
+    defaults: ["libaudioclient_gtests_defaults"],
+    srcs: [
+        "audiosystem_tests.cpp",
+        "audio_test_utils.cpp",
+    ],
+}
diff --git a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
index 997f62a..e2216a0 100644
--- a/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_legacy_conversion_tests.cpp
@@ -14,24 +14,68 @@
  * limitations under the License.
  */
 
+#include <iostream>
+
 #include <gtest/gtest.h>
 
-#include <media/AudioCommonTypes.h>
 #include <media/AidlConversion.h>
+#include <media/AudioCommonTypes.h>
 
 using namespace android;
 using namespace android::aidl_utils;
 
+using media::AudioDirectMode;
+using media::AudioPortConfigFw;
+using media::AudioPortDeviceExtSys;
+using media::AudioPortFw;
+using media::AudioPortRole;
+using media::AudioPortType;
 using media::audio::common::AudioChannelLayout;
+using media::audio::common::AudioDevice;
 using media::audio::common::AudioDeviceDescription;
 using media::audio::common::AudioDeviceType;
+using media::audio::common::AudioEncapsulationMetadataType;
+using media::audio::common::AudioEncapsulationType;
 using media::audio::common::AudioFormatDescription;
 using media::audio::common::AudioFormatType;
+using media::audio::common::AudioGain;
+using media::audio::common::AudioGainConfig;
+using media::audio::common::AudioGainMode;
+using media::audio::common::AudioIoFlags;
+using media::audio::common::AudioPortDeviceExt;
+using media::audio::common::AudioProfile;
+using media::audio::common::AudioStandard;
+using media::audio::common::ExtraAudioDescriptor;
+using media::audio::common::Int;
+using media::audio::common::MicrophoneDynamicInfo;
+using media::audio::common::MicrophoneInfo;
 using media::audio::common::PcmType;
 
+// Provide value printers for types generated from AIDL
+// They need to be in the same namespace as the types we intend to print
+namespace android::media {
+#define DEFINE_PRINTING_TEMPLATES()                                                               \
+    template <typename P>                                                                         \
+    std::enable_if_t<std::is_base_of_v<::android::Parcelable, P>, std::ostream&> operator<<(      \
+            std::ostream& os, const P& p) {                                                       \
+        return os << p.toString();                                                                \
+    }                                                                                             \
+    template <typename E>                                                                         \
+    std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) { \
+        return os << toString(e);                                                                 \
+    }
+DEFINE_PRINTING_TEMPLATES();
+
+namespace audio::common {
+DEFINE_PRINTING_TEMPLATES();
+}  // namespace audio::common
+#undef DEFINE_PRINTING_TEMPLATES
+}  // namespace android::media
+
 namespace {
 
-template<typename T> size_t hash(const T& t) {
+template <typename T>
+size_t hash(const T& t) {
     return std::hash<T>{}(t);
 }
 
@@ -52,10 +96,8 @@
     return AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
             // Use channels that exist both for input and output,
             // but doesn't form a known layout mask.
-            AudioChannelLayout::CHANNEL_FRONT_LEFT |
-            AudioChannelLayout::CHANNEL_FRONT_RIGHT |
-            AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT |
-            AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT);
+            AudioChannelLayout::CHANNEL_FRONT_LEFT | AudioChannelLayout::CHANNEL_FRONT_RIGHT |
+            AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT | AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT);
 }
 
 AudioChannelLayout make_ACL_ChannelIndex2() {
@@ -74,7 +116,7 @@
 }
 
 AudioDeviceDescription make_AudioDeviceDescription(AudioDeviceType type,
-        const std::string& connection = "") {
+                                                   const std::string& connection = "") {
     AudioDeviceDescription result;
     result.type = type;
     result.connection = connection;
@@ -95,12 +137,12 @@
 
 AudioDeviceDescription make_ADD_WiredHeadset() {
     return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
-            AudioDeviceDescription::CONNECTION_ANALOG());
+                                       AudioDeviceDescription::CONNECTION_ANALOG());
 }
 
 AudioDeviceDescription make_ADD_BtScoHeadset() {
     return make_AudioDeviceDescription(AudioDeviceType::OUT_HEADSET,
-            AudioDeviceDescription::CONNECTION_BT_SCO());
+                                       AudioDeviceDescription::CONNECTION_BT_SCO());
 }
 
 AudioFormatDescription make_AudioFormatDescription(AudioFormatType type) {
@@ -121,8 +163,7 @@
     return result;
 }
 
-AudioFormatDescription make_AudioFormatDescription(PcmType transport,
-        const std::string& encoding) {
+AudioFormatDescription make_AudioFormatDescription(PcmType transport, const std::string& encoding) {
     auto result = make_AudioFormatDescription(encoding);
     result.pcm = transport;
     return result;
@@ -154,6 +195,22 @@
     return afd;
 }
 
+android::media::TrackSecondaryOutputInfo make_TrackSecondaryOutputInfo() {
+    android::media::TrackSecondaryOutputInfo result;
+    result.portId = 1;
+    result.secondaryOutputIds = {0, 5, 7};
+    return result;
+}
+
+ExtraAudioDescriptor make_ExtraAudioDescriptor(AudioStandard audioStandard,
+                                               AudioEncapsulationType audioEncapsulationType) {
+    ExtraAudioDescriptor result;
+    result.standard = audioStandard;
+    result.audioDescriptor = {0xb4, 0xaf, 0x98, 0x1a};
+    result.encapsulationType = audioEncapsulationType;
+    return result;
+}
+
 }  // namespace
 
 // Verify that two independently constructed ADDs/AFDs have the same hash.
@@ -163,7 +220,8 @@
 // is identical to the same format description constructed by the framework.
 class HashIdentityTest : public ::testing::Test {
   public:
-    template<typename T> void verifyHashIdentity(const std::vector<std::function<T()>>& valueGens) {
+    template <typename T>
+    void verifyHashIdentity(const std::vector<std::function<T()>>& valueGens) {
         for (size_t i = 0; i < valueGens.size(); ++i) {
             for (size_t j = 0; j < valueGens.size(); ++j) {
                 if (i == j) {
@@ -177,27 +235,25 @@
 };
 
 TEST_F(HashIdentityTest, AudioChannelLayoutHashIdentity) {
-    verifyHashIdentity<AudioChannelLayout>({
-            make_ACL_None, make_ACL_Invalid, make_ACL_Stereo,
-            make_ACL_LayoutArbitrary, make_ACL_ChannelIndex2,
-            make_ACL_ChannelIndexArbitrary, make_ACL_VoiceCall});
+    verifyHashIdentity<AudioChannelLayout>({make_ACL_None, make_ACL_Invalid, make_ACL_Stereo,
+                                            make_ACL_LayoutArbitrary, make_ACL_ChannelIndex2,
+                                            make_ACL_ChannelIndexArbitrary, make_ACL_VoiceCall});
 }
 
 TEST_F(HashIdentityTest, AudioDeviceDescriptionHashIdentity) {
-    verifyHashIdentity<AudioDeviceDescription>({
-            make_ADD_None, make_ADD_DefaultIn, make_ADD_DefaultOut, make_ADD_WiredHeadset,
-            make_ADD_BtScoHeadset});
+    verifyHashIdentity<AudioDeviceDescription>({make_ADD_None, make_ADD_DefaultIn,
+                                                make_ADD_DefaultOut, make_ADD_WiredHeadset,
+                                                make_ADD_BtScoHeadset});
 }
 
 TEST_F(HashIdentityTest, AudioFormatDescriptionHashIdentity) {
-    verifyHashIdentity<AudioFormatDescription>({
-            make_AFD_Default, make_AFD_Invalid, make_AFD_Pcm16Bit, make_AFD_Bitstream,
-            make_AFD_Encap, make_AFD_Encap_with_Enc});
+    verifyHashIdentity<AudioFormatDescription>({make_AFD_Default, make_AFD_Invalid,
+                                                make_AFD_Pcm16Bit, make_AFD_Bitstream,
+                                                make_AFD_Encap, make_AFD_Encap_with_Enc});
 }
 
 using ChannelLayoutParam = std::tuple<AudioChannelLayout, bool /*isInput*/>;
-class AudioChannelLayoutRoundTripTest :
-        public testing::TestWithParam<ChannelLayoutParam> {};
+class AudioChannelLayoutRoundTripTest : public testing::TestWithParam<ChannelLayoutParam> {};
 TEST_P(AudioChannelLayoutRoundTripTest, Aidl2Legacy2Aidl) {
     const auto initial = std::get<0>(GetParam());
     const bool isInput = std::get<1>(GetParam());
@@ -207,21 +263,82 @@
     ASSERT_TRUE(convBack.ok());
     EXPECT_EQ(initial, convBack.value());
 }
-INSTANTIATE_TEST_SUITE_P(AudioChannelLayoutRoundTrip,
-        AudioChannelLayoutRoundTripTest,
+
+INSTANTIATE_TEST_SUITE_P(
+        AudioChannelLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
         testing::Combine(
                 testing::Values(AudioChannelLayout{}, make_ACL_Invalid(), make_ACL_Stereo(),
-                        make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
-                        make_ACL_ChannelIndexArbitrary()),
+                                make_ACL_LayoutArbitrary(), make_ACL_ChannelIndex2(),
+                                make_ACL_ChannelIndexArbitrary(),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_BACK_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_BACK_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_BACK_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_LOW_FREQUENCY),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_SIDE_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_SIDE_RIGHT)),
                 testing::Values(false, true)));
-INSTANTIATE_TEST_SUITE_P(AudioChannelVoiceRoundTrip,
-        AudioChannelLayoutRoundTripTest,
-        // In legacy constants the voice call is only defined for input.
-        testing::Combine(testing::Values(make_ACL_VoiceCall()), testing::Values(true)));
+INSTANTIATE_TEST_SUITE_P(AudioChannelVoiceRoundTrip, AudioChannelLayoutRoundTripTest,
+                         // In legacy constants the voice call is only defined for input.
+                         testing::Combine(testing::Values(make_ACL_VoiceCall()),
+                                          testing::Values(true)));
+
+INSTANTIATE_TEST_SUITE_P(
+        OutAudioChannelLayoutLayoutRoundTrip, AudioChannelLayoutRoundTripTest,
+        testing::Combine(
+                testing::Values(AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_LEFT_OF_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_RIGHT_OF_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_SIDE_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_SIDE_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_FRONT_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_FRONT_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_FRONT_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_BACK_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_BACK_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_TOP_BACK_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_BOTTOM_FRONT_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_BOTTOM_FRONT_CENTER),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_BOTTOM_FRONT_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_LOW_FREQUENCY_2),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_HAPTIC_A),
+                                AudioChannelLayout::make<AudioChannelLayout::Tag::layoutMask>(
+                                        AudioChannelLayout::CHANNEL_HAPTIC_B)),
+                testing::Values(false)));
 
 using ChannelLayoutEdgeCaseParam = std::tuple<int /*legacy*/, bool /*isInput*/, bool /*isValid*/>;
-class AudioChannelLayoutEdgeCaseTest :
-        public testing::TestWithParam<ChannelLayoutEdgeCaseParam> {};
+class AudioChannelLayoutEdgeCaseTest : public testing::TestWithParam<ChannelLayoutEdgeCaseParam> {};
 TEST_P(AudioChannelLayoutEdgeCaseTest, Legacy2Aidl) {
     const audio_channel_mask_t legacy = static_cast<audio_channel_mask_t>(std::get<0>(GetParam()));
     const bool isInput = std::get<1>(GetParam());
@@ -229,8 +346,8 @@
     auto conv = legacy2aidl_audio_channel_mask_t_AudioChannelLayout(legacy, isInput);
     EXPECT_EQ(isValid, conv.ok());
 }
-INSTANTIATE_TEST_SUITE_P(AudioChannelLayoutEdgeCase,
-        AudioChannelLayoutEdgeCaseTest,
+INSTANTIATE_TEST_SUITE_P(
+        AudioChannelLayoutEdgeCase, AudioChannelLayoutEdgeCaseTest,
         testing::Values(
                 // Valid legacy input masks.
                 std::make_tuple(AUDIO_CHANNEL_IN_VOICE_UPLINK_MONO, true, true),
@@ -240,25 +357,26 @@
                 std::make_tuple(
                         // This has the same numerical representation as Mask 'A' below
                         AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                        AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT, false, true),
+                                AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT,
+                        false, true),
                 std::make_tuple(
                         // This has the same numerical representation as Mask 'B' below
                         AUDIO_CHANNEL_OUT_FRONT_CENTER | AUDIO_CHANNEL_OUT_LOW_FREQUENCY |
-                        AUDIO_CHANNEL_OUT_TOP_BACK_LEFT, false, true),
+                                AUDIO_CHANNEL_OUT_TOP_BACK_LEFT,
+                        false, true),
                 // Invalid legacy input masks.
                 std::make_tuple(AUDIO_CHANNEL_IN_6, true, false),
-                std::make_tuple(
-                        AUDIO_CHANNEL_IN_6 | AUDIO_CHANNEL_IN_FRONT_PROCESSED, true, false),
-                std::make_tuple(
-                        AUDIO_CHANNEL_IN_PRESSURE | AUDIO_CHANNEL_IN_X_AXIS |
-                        AUDIO_CHANNEL_IN_Y_AXIS | AUDIO_CHANNEL_IN_Z_AXIS, true, false),
+                std::make_tuple(AUDIO_CHANNEL_IN_6 | AUDIO_CHANNEL_IN_FRONT_PROCESSED, true, false),
+                std::make_tuple(AUDIO_CHANNEL_IN_PRESSURE | AUDIO_CHANNEL_IN_X_AXIS |
+                                        AUDIO_CHANNEL_IN_Y_AXIS | AUDIO_CHANNEL_IN_Z_AXIS,
+                                true, false),
                 std::make_tuple(  // Mask 'A'
                         AUDIO_CHANNEL_IN_STEREO | AUDIO_CHANNEL_IN_VOICE_UPLINK, true, false),
                 std::make_tuple(  // Mask 'B'
                         AUDIO_CHANNEL_IN_STEREO | AUDIO_CHANNEL_IN_VOICE_DNLINK, true, false)));
 
-class AudioDeviceDescriptionRoundTripTest :
-        public testing::TestWithParam<AudioDeviceDescription> {};
+class AudioDeviceDescriptionRoundTripTest : public testing::TestWithParam<AudioDeviceDescription> {
+};
 TEST_P(AudioDeviceDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
     const auto initial = GetParam();
     auto conv = aidl2legacy_AudioDeviceDescription_audio_devices_t(initial);
@@ -267,13 +385,13 @@
     ASSERT_TRUE(convBack.ok());
     EXPECT_EQ(initial, convBack.value());
 }
-INSTANTIATE_TEST_SUITE_P(AudioDeviceDescriptionRoundTrip,
-        AudioDeviceDescriptionRoundTripTest,
-        testing::Values(AudioDeviceDescription{}, make_ADD_DefaultIn(),
-                make_ADD_DefaultOut(), make_ADD_WiredHeadset(), make_ADD_BtScoHeadset()));
+INSTANTIATE_TEST_SUITE_P(AudioDeviceDescriptionRoundTrip, AudioDeviceDescriptionRoundTripTest,
+                         testing::Values(AudioDeviceDescription{}, make_ADD_DefaultIn(),
+                                         make_ADD_DefaultOut(), make_ADD_WiredHeadset(),
+                                         make_ADD_BtScoHeadset()));
 
-class AudioFormatDescriptionRoundTripTest :
-        public testing::TestWithParam<AudioFormatDescription> {};
+class AudioFormatDescriptionRoundTripTest : public testing::TestWithParam<AudioFormatDescription> {
+};
 TEST_P(AudioFormatDescriptionRoundTripTest, Aidl2Legacy2Aidl) {
     const auto initial = GetParam();
     auto conv = aidl2legacy_AudioFormatDescription_audio_format_t(initial);
@@ -282,6 +400,338 @@
     ASSERT_TRUE(convBack.ok());
     EXPECT_EQ(initial, convBack.value());
 }
-INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip,
-        AudioFormatDescriptionRoundTripTest,
-        testing::Values(make_AFD_Invalid(), AudioFormatDescription{}, make_AFD_Pcm16Bit()));
+INSTANTIATE_TEST_SUITE_P(AudioFormatDescriptionRoundTrip, AudioFormatDescriptionRoundTripTest,
+                         testing::Values(make_AFD_Invalid(), AudioFormatDescription{},
+                                         make_AFD_Pcm16Bit()));
+
+AudioPortConfigFw createAudioPortConfigFw(const AudioChannelLayout& layout,
+                                          const AudioFormatDescription& format,
+                                          const AudioDeviceDescription& device) {
+    const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+    AudioPortConfigFw result;
+    result.hal.id = 43;
+    result.hal.portId = 42;
+    Int sr44100;
+    sr44100.value = 44100;
+    result.hal.sampleRate = sr44100;
+    result.hal.channelMask = layout;
+    result.hal.format = format;
+    AudioGainConfig gain;
+    gain.mode = 1 << static_cast<int>(AudioGainMode::JOINT);
+    gain.values = std::vector<int32_t>({100});
+    result.hal.gain = gain;
+    AudioPortDeviceExt ext;
+    AudioDevice audioDevice;
+    audioDevice.type = device;
+    ext.device = audioDevice;
+    result.hal.ext = ext;
+    result.sys.role = isInput ? AudioPortRole::SOURCE : AudioPortRole::SINK;
+    result.sys.type = AudioPortType::DEVICE;
+    AudioPortDeviceExtSys sysDevice;
+    sysDevice.hwModule = 1;
+    result.sys.ext = sysDevice;
+    return result;
+}
+
+using AudioPortConfigParam =
+        std::tuple<AudioChannelLayout, AudioFormatDescription, AudioDeviceDescription>;
+class AudioPortConfigRoundTripTest : public testing::TestWithParam<AudioPortConfigParam> {};
+TEST_P(AudioPortConfigRoundTripTest, Aidl2Legacy2Aidl) {
+    const AudioChannelLayout layout = std::get<0>(GetParam());
+    const AudioFormatDescription format = std::get<1>(GetParam());
+    const AudioDeviceDescription device = std::get<2>(GetParam());
+    const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+    AudioPortConfigFw initial = createAudioPortConfigFw(layout, format, device);
+    {
+        audio_port_config conv{};
+        int32_t portId = -1;
+        status_t status =
+                aidl2legacy_AudioPortConfig_audio_port_config(initial.hal, isInput, &conv, &portId);
+        ASSERT_EQ(OK, status);
+        EXPECT_NE(-1, portId);
+        auto convBack = legacy2aidl_audio_port_config_AudioPortConfig(conv, isInput, portId);
+        ASSERT_TRUE(convBack.ok());
+        EXPECT_EQ(initial.hal, convBack.value());
+    }
+    {
+        int32_t portId = -1;
+        auto conv = aidl2legacy_AudioPortConfigFw_audio_port_config(initial, &portId);
+        ASSERT_TRUE(conv.ok());
+        EXPECT_NE(-1, portId);
+        auto convBack = legacy2aidl_audio_port_config_AudioPortConfigFw(conv.value(), portId);
+        ASSERT_TRUE(convBack.ok());
+        EXPECT_EQ(initial, convBack.value());
+    }
+}
+INSTANTIATE_TEST_SUITE_P(
+        AudioPortConfig, AudioPortConfigRoundTripTest,
+        testing::Combine(testing::Values(make_ACL_Stereo(), make_ACL_ChannelIndex2()),
+                         testing::Values(make_AFD_Pcm16Bit()),
+                         testing::Values(make_ADD_DefaultIn(), make_ADD_DefaultOut(),
+                                         make_ADD_WiredHeadset())));
+
+class AudioPortFwRoundTripTest : public testing::TestWithParam<AudioDeviceDescription> {
+  public:
+    AudioProfile createProfile(const AudioFormatDescription& format,
+                               const std::vector<AudioChannelLayout>& channelMasks,
+                               const std::vector<int32_t>& sampleRates) {
+        AudioProfile profile;
+        profile.format = format;
+        profile.channelMasks = channelMasks;
+        profile.sampleRates = sampleRates;
+        return profile;
+    }
+};
+TEST_P(AudioPortFwRoundTripTest, Aidl2Legacy2Aidl) {
+    const AudioDeviceDescription device = GetParam();
+    const bool isInput = device.type < AudioDeviceType::OUT_DEFAULT;
+    AudioPortFw initial;
+    initial.hal.id = 42;
+    initial.hal.profiles.push_back(createProfile(
+            make_AFD_Pcm16Bit(), {make_ACL_Stereo(), make_ACL_ChannelIndex2()}, {44100, 48000}));
+    if (isInput) {
+        initial.hal.flags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
+    } else {
+        initial.hal.flags = AudioIoFlags::make<AudioIoFlags::Tag::output>(0);
+    }
+    AudioGain initialGain;
+    initialGain.mode = 1 << static_cast<int>(AudioGainMode::JOINT);
+    initialGain.channelMask = make_ACL_Stereo();
+    initial.hal.gains.push_back(initialGain);
+    AudioPortDeviceExt initialExt;
+    AudioDevice initialDevice;
+    initialDevice.type = device;
+    initialExt.device = initialDevice;
+    initial.hal.ext = initialExt;
+    {
+        auto conv = aidl2legacy_AudioPort_audio_port_v7(initial.hal, isInput);
+        ASSERT_TRUE(conv.ok());
+        auto convBack = legacy2aidl_audio_port_v7_AudioPort(conv.value(), isInput);
+        ASSERT_TRUE(convBack.ok());
+        EXPECT_EQ(initial.hal, convBack.value());
+    }
+    initial.sys.role = isInput ? AudioPortRole::SOURCE : AudioPortRole::SINK;
+    initial.sys.type = AudioPortType::DEVICE;
+    initial.sys.profiles.resize(initial.hal.profiles.size());
+    initial.sys.gains.resize(initial.hal.gains.size());
+    initial.sys.activeConfig =
+            createAudioPortConfigFw(make_ACL_Stereo(), make_AFD_Pcm16Bit(), device);
+    initial.sys.activeConfig.hal.flags = initial.hal.flags;
+    AudioPortDeviceExtSys initialSysDevice;
+    initialSysDevice.hwModule = 1;
+    initial.sys.ext = initialSysDevice;
+    {
+        auto conv = aidl2legacy_AudioPortFw_audio_port_v7(initial);
+        ASSERT_TRUE(conv.ok());
+        auto convBack = legacy2aidl_audio_port_v7_AudioPortFw(conv.value());
+        ASSERT_TRUE(convBack.ok());
+        EXPECT_EQ(initial, convBack.value());
+    }
+}
+INSTANTIATE_TEST_SUITE_P(AudioPortFw, AudioPortFwRoundTripTest,
+                         testing::Values(make_ADD_DefaultIn(), make_ADD_DefaultOut(),
+                                         make_ADD_WiredHeadset()));
+
+class AudioDirectModeRoundTripTest : public testing::TestWithParam<AudioDirectMode> {};
+TEST_P(AudioDirectModeRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto initial = GetParam();
+    auto conv = aidl2legacy_AudioDirectMode_audio_direct_mode_t(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_direct_mode_t_AudioDirectMode(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioDirectMode, AudioDirectModeRoundTripTest,
+                         testing::Values(AudioDirectMode::NONE, AudioDirectMode::OFFLOAD,
+                                         AudioDirectMode::OFFLOAD_GAPLESS,
+                                         AudioDirectMode::BITSTREAM));
+
+class AudioStandardRoundTripTest : public testing::TestWithParam<AudioStandard> {};
+TEST_P(AudioStandardRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto initial = GetParam();
+    auto conv = aidl2legacy_AudioStandard_audio_standard_t(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_standard_t_AudioStandard(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioStandard, AudioStandardRoundTripTest,
+                         testing::Values(AudioStandard::NONE, AudioStandard::EDID));
+
+class AudioEncapsulationMetadataTypeRoundTripTest
+    : public testing::TestWithParam<AudioEncapsulationMetadataType> {};
+TEST_P(AudioEncapsulationMetadataTypeRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto initial = GetParam();
+    auto conv =
+            aidl2legacy_AudioEncapsulationMetadataType_audio_encapsulation_metadata_type_t(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_encapsulation_metadata_type_t_AudioEncapsulationMetadataType(
+            conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioEncapsulationMetadataType,
+                         AudioEncapsulationMetadataTypeRoundTripTest,
+                         testing::Values(AudioEncapsulationMetadataType::NONE,
+                                         AudioEncapsulationMetadataType::FRAMEWORK_TUNER,
+                                         AudioEncapsulationMetadataType::DVB_AD_DESCRIPTOR));
+
+class AudioGainModeRoundTripTest : public testing::TestWithParam<AudioGainMode> {};
+TEST_P(AudioGainModeRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto initial = GetParam();
+    auto conv = aidl2legacy_AudioGainMode_audio_gain_mode_t(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_gain_mode_t_AudioGainMode(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+INSTANTIATE_TEST_SUITE_P(AudioGainMode, AudioGainModeRoundTripTest,
+                         testing::Values(AudioGainMode::JOINT, AudioGainMode::CHANNELS,
+                                         AudioGainMode::RAMP));
+
+TEST(AudioTrackSecondaryOutputInfoRoundTripTest, Aidl2Legacy2Aidl) {
+    const auto initial = make_TrackSecondaryOutputInfo();
+    auto conv = aidl2legacy_TrackSecondaryOutputInfo_TrackSecondaryOutputInfoPair(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_TrackSecondaryOutputInfoPair_TrackSecondaryOutputInfo(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+
+using ExtraAudioDescriptorParam = std::tuple<AudioStandard, AudioEncapsulationType>;
+class ExtraAudioDescriptorRoundTripTest : public testing::TestWithParam<ExtraAudioDescriptorParam> {
+};
+TEST_P(ExtraAudioDescriptorRoundTripTest, Aidl2Legacy2Aidl) {
+    ExtraAudioDescriptor initial =
+            make_ExtraAudioDescriptor(std::get<0>(GetParam()), std::get<1>(GetParam()));
+    auto conv = aidl2legacy_ExtraAudioDescriptor_audio_extra_audio_descriptor(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_extra_audio_descriptor_ExtraAudioDescriptor(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        ExtraAudioDescriptor, ExtraAudioDescriptorRoundTripTest,
+        testing::Values(std::make_tuple(AudioStandard::NONE, AudioEncapsulationType::NONE),
+                        std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::NONE),
+                        std::make_tuple(AudioStandard::EDID, AudioEncapsulationType::IEC61937)));
+
+TEST(AudioPortSessionExtRoundTripTest, Aidl2Legacy2Aidl) {
+    const int32_t initial = 7;
+    auto conv = aidl2legacy_int32_t_audio_port_session_ext(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_port_session_ext_int32_t(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+
+class AudioGainTest : public testing::TestWithParam<bool> {};
+TEST_P(AudioGainTest, Legacy2Aidl2Legacy) {
+    audio_port_v7 port;
+    port.num_gains = 2;
+    port.gains[0] = {.mode = AUDIO_GAIN_MODE_JOINT,
+                     .channel_mask = AUDIO_CHANNEL_IN_STEREO,
+                     .min_value = -3200,
+                     .max_value = 600,
+                     .default_value = 0,
+                     .step_value = 100,
+                     .min_ramp_ms = 10,
+                     .max_ramp_ms = 20};
+    port.gains[1] = {.mode = AUDIO_GAIN_MODE_JOINT,
+                     .channel_mask = AUDIO_CHANNEL_IN_MONO,
+                     .min_value = -8800,
+                     .max_value = 4000,
+                     .default_value = 0,
+                     .step_value = 100,
+                     .min_ramp_ms = 192,
+                     .max_ramp_ms = 224};
+
+    const auto isInput = GetParam();
+    for (int i = 0; i < port.num_gains; i++) {
+        auto initial = port.gains[i];
+        auto conv = legacy2aidl_audio_gain_AudioGain(initial, isInput);
+        ASSERT_TRUE(conv.ok());
+        auto convBack = aidl2legacy_AudioGain_audio_gain(conv.value(), isInput);
+        ASSERT_TRUE(convBack.ok());
+        EXPECT_EQ(initial.mode, convBack.value().mode);
+        EXPECT_EQ(initial.channel_mask, convBack.value().channel_mask);
+        EXPECT_EQ(initial.min_value, convBack.value().min_value);
+        EXPECT_EQ(initial.max_value, convBack.value().max_value);
+        EXPECT_EQ(initial.default_value, convBack.value().default_value);
+        EXPECT_EQ(initial.step_value, convBack.value().step_value);
+        EXPECT_EQ(initial.min_ramp_ms, convBack.value().min_ramp_ms);
+        EXPECT_EQ(initial.max_ramp_ms, convBack.value().max_ramp_ms);
+    }
+}
+INSTANTIATE_TEST_SUITE_P(AudioGain, AudioGainTest, testing::Values(true, false));
+
+TEST(AudioMicrophoneInfoFw, Aidl2Legacy2Aidl) {
+    media::MicrophoneInfoFw initial{};
+    // HALs must return at least 1 element in channelMapping. The zero value is 'UNUSED'.
+    initial.dynamic.channelMapping.resize(1);
+    auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(initial);
+    ASSERT_TRUE(conv.ok());
+    auto convBack = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(conv.value());
+    ASSERT_TRUE(convBack.ok());
+    EXPECT_EQ(initial, convBack.value());
+}
+
+TEST(AudioMicrophoneInfoFw, UnknownValues) {
+    {
+        media::MicrophoneInfoFw initial;
+        initial.dynamic.channelMapping.resize(1);
+        initial.info.indexInTheGroup = MicrophoneInfo::INDEX_IN_THE_GROUP_UNKNOWN;
+        auto conv = aidl2legacy_MicrophoneInfoFw_audio_microphone_characteristic_t(initial);
+        ASSERT_TRUE(conv.ok());
+        auto convBack =
+                legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(conv.value());
+        ASSERT_TRUE(convBack.ok());
+        EXPECT_EQ(initial, convBack.value());
+    }
+    for (const auto f : {&audio_microphone_characteristic_t::sensitivity,
+                         &audio_microphone_characteristic_t::max_spl,
+                         &audio_microphone_characteristic_t::min_spl}) {
+        audio_microphone_characteristic_t mic{};
+        if (f == &audio_microphone_characteristic_t::sensitivity) {
+            mic.*f = AUDIO_MICROPHONE_SENSITIVITY_UNKNOWN;
+        } else {
+            mic.*f = AUDIO_MICROPHONE_SPL_UNKNOWN;
+        }
+        auto aidl = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+        ASSERT_TRUE(aidl.ok());
+        EXPECT_FALSE(aidl.value().info.sensitivity.has_value());
+    }
+    for (const auto f : {&audio_microphone_characteristic_t::geometric_location,
+                         &audio_microphone_characteristic_t::orientation}) {
+        for (const auto c : {&audio_microphone_coordinate::x, &audio_microphone_coordinate::y,
+                             &audio_microphone_coordinate::z}) {
+            audio_microphone_characteristic_t mic{};
+            mic.*f.*c = AUDIO_MICROPHONE_COORDINATE_UNKNOWN;
+            auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+            ASSERT_TRUE(conv.ok());
+            const auto& aidl = conv.value();
+            if (f == &audio_microphone_characteristic_t::geometric_location) {
+                EXPECT_FALSE(aidl.info.position.has_value());
+                EXPECT_TRUE(aidl.info.orientation.has_value());
+            } else {
+                EXPECT_TRUE(aidl.info.position.has_value());
+                EXPECT_FALSE(aidl.info.orientation.has_value());
+            }
+        }
+    }
+}
+
+TEST(AudioMicrophoneInfoFw, ChannelMapping) {
+    audio_microphone_characteristic_t mic{};
+    mic.channel_mapping[1] = AUDIO_MICROPHONE_CHANNEL_MAPPING_DIRECT;
+    mic.channel_mapping[3] = AUDIO_MICROPHONE_CHANNEL_MAPPING_PROCESSED;
+    auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+    ASSERT_TRUE(conv.ok());
+    const auto& aidl = conv.value();
+    EXPECT_EQ(4, aidl.dynamic.channelMapping.size());
+    EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::UNUSED, aidl.dynamic.channelMapping[0]);
+    EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::DIRECT, aidl.dynamic.channelMapping[1]);
+    EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::UNUSED, aidl.dynamic.channelMapping[2]);
+    EXPECT_EQ(MicrophoneDynamicInfo::ChannelMapping::PROCESSED, aidl.dynamic.channelMapping[3]);
+}
diff --git a/media/libaudioclient/tests/audio_aidl_status_tests.cpp b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
index 5517091..8a7e6c1 100644
--- a/media/libaudioclient/tests/audio_aidl_status_tests.cpp
+++ b/media/libaudioclient/tests/audio_aidl_status_tests.cpp
@@ -37,25 +37,10 @@
 
 // Special status values are preserved on round trip.
 TEST(audio_aidl_status_tests, statusRoundTripSpecialValues) {
-    for (status_t status : {
-            OK,
-            UNKNOWN_ERROR,
-            NO_MEMORY,
-            INVALID_OPERATION,
-            BAD_VALUE,
-            BAD_TYPE,
-            NAME_NOT_FOUND,
-            PERMISSION_DENIED,
-            NO_INIT,
-            ALREADY_EXISTS,
-            DEAD_OBJECT,
-            FAILED_TRANSACTION,
-            BAD_INDEX,
-            NOT_ENOUGH_DATA,
-            WOULD_BLOCK,
-            TIMED_OUT,
-            UNKNOWN_TRANSACTION,
-            FDS_NOT_ALLOWED}) {
+    for (status_t status :
+         {OK, UNKNOWN_ERROR, NO_MEMORY, INVALID_OPERATION, BAD_VALUE, BAD_TYPE, NAME_NOT_FOUND,
+          PERMISSION_DENIED, NO_INIT, ALREADY_EXISTS, DEAD_OBJECT, FAILED_TRANSACTION, BAD_INDEX,
+          NOT_ENOUGH_DATA, WOULD_BLOCK, TIMED_OUT, UNKNOWN_TRANSACTION, FDS_NOT_ALLOWED}) {
         ASSERT_EQ(status, statusTFromBinderStatus(binderStatusFromStatusT(status)));
     }
 }
@@ -63,47 +48,29 @@
 // Binder exceptions show as an error (not fixed at this time); these come fromExceptionCode().
 TEST(audio_aidl_status_tests, binderStatusExceptions) {
     for (int exceptionCode : {
-            //Status::EX_NONE,
-            Status::EX_SECURITY,
-            Status::EX_BAD_PARCELABLE,
-            Status::EX_ILLEGAL_ARGUMENT,
-            Status::EX_NULL_POINTER,
-            Status::EX_ILLEGAL_STATE,
-            Status::EX_NETWORK_MAIN_THREAD,
-            Status::EX_UNSUPPORTED_OPERATION,
-            //Status::EX_SERVICE_SPECIFIC, -- tested fromServiceSpecificError()
-            Status::EX_PARCELABLE,
-            // This is special and Java specific; see Parcel.java.
-            Status::EX_HAS_REPLY_HEADER,
-            // This is special, and indicates to C++ binder proxies that the
-            // transaction has failed at a low level.
-            //Status::EX_TRANSACTION_FAILED, -- tested fromStatusT().
-            }) {
+                 // Status::EX_NONE,
+                 Status::EX_SECURITY, Status::EX_BAD_PARCELABLE, Status::EX_ILLEGAL_ARGUMENT,
+                 Status::EX_NULL_POINTER, Status::EX_ILLEGAL_STATE, Status::EX_NETWORK_MAIN_THREAD,
+                 Status::EX_UNSUPPORTED_OPERATION,
+                 // Status::EX_SERVICE_SPECIFIC, -- tested fromServiceSpecificError()
+                 Status::EX_PARCELABLE,
+                 // This is special and Java specific; see Parcel.java.
+                 Status::EX_HAS_REPLY_HEADER,
+                 // This is special, and indicates to C++ binder proxies that the
+                 // transaction has failed at a low level.
+                 // Status::EX_TRANSACTION_FAILED, -- tested fromStatusT().
+         }) {
         ASSERT_NE(OK, statusTFromBinderStatus(Status::fromExceptionCode(exceptionCode)));
     }
 }
 
 // Binder transaction errors show exactly in status_t; these come fromStatusT().
 TEST(audio_aidl_status_tests, binderStatusTransactionError) {
-    for (status_t status : {
-            OK, // Note: fromStatusT does check if this is 0, so this is no error.
-            UNKNOWN_ERROR,
-            NO_MEMORY,
-            INVALID_OPERATION,
-            BAD_VALUE,
-            BAD_TYPE,
-            NAME_NOT_FOUND,
-            PERMISSION_DENIED,
-            NO_INIT,
-            ALREADY_EXISTS,
-            DEAD_OBJECT,
-            FAILED_TRANSACTION,
-            BAD_INDEX,
-            NOT_ENOUGH_DATA,
-            WOULD_BLOCK,
-            TIMED_OUT,
-            UNKNOWN_TRANSACTION,
-            FDS_NOT_ALLOWED}) {
+    for (status_t status :
+         {OK,  // Note: fromStatusT does check if this is 0, so this is no error.
+          UNKNOWN_ERROR, NO_MEMORY, INVALID_OPERATION, BAD_VALUE, BAD_TYPE, NAME_NOT_FOUND,
+          PERMISSION_DENIED, NO_INIT, ALREADY_EXISTS, DEAD_OBJECT, FAILED_TRANSACTION, BAD_INDEX,
+          NOT_ENOUGH_DATA, WOULD_BLOCK, TIMED_OUT, UNKNOWN_TRANSACTION, FDS_NOT_ALLOWED}) {
         ASSERT_EQ(status, statusTFromBinderStatus(Status::fromStatusT(status)));
     }
 }
diff --git a/media/libaudioclient/tests/audio_test_template.xml b/media/libaudioclient/tests/audio_test_template.xml
new file mode 100644
index 0000000..ed0cb21
--- /dev/null
+++ b/media/libaudioclient/tests/audio_test_template.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the"License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an"AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Unit test configuration for {MODULE}">
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="{MODULE}" value="/data/local/tmp/{MODULE}" />
+
+        <!-- Files used for audio testing -->
+        <option name="push-file" key="bbb_1ch_8kHz_s16le.raw" value="/data/local/tmp/bbb_1ch_8kHz_s16le.raw" />
+        <option name="push-file" key="bbb_2ch_24kHz_s16le.raw" value="/data/local/tmp/bbb_2ch_24kHz_s16le.raw" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="{MODULE}" />
+    </test>
+</configuration>
diff --git a/media/libaudioclient/tests/audio_test_utils.cpp b/media/libaudioclient/tests/audio_test_utils.cpp
new file mode 100644
index 0000000..1e26ff6
--- /dev/null
+++ b/media/libaudioclient/tests/audio_test_utils.cpp
@@ -0,0 +1,910 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioTestUtils"
+
+#include <android-base/file.h>
+#include <system/audio_config.h>
+#include <utils/Log.h>
+
+#include "audio_test_utils.h"
+
+#define WAIT_PERIOD_MS 10  // from AudioTrack.cpp
+#define MAX_WAIT_TIME_MS 5000
+
+template <class T>
+constexpr void (*xmlDeleter)(T* t);
+template <>
+constexpr auto xmlDeleter<xmlDoc> = xmlFreeDoc;
+template <>
+constexpr auto xmlDeleter<xmlChar> = [](xmlChar* s) { xmlFree(s); };
+
+/** @return a unique_ptr with the correct deleter for the libxml2 object. */
+template <class T>
+constexpr auto make_xmlUnique(T* t) {
+    // Wrap deleter in lambda to enable empty base optimization
+    auto deleter = [](T* t) { xmlDeleter<T>(t); };
+    return std::unique_ptr<T, decltype(deleter)>{t, deleter};
+}
+
+void OnAudioDeviceUpdateNotifier::onAudioDeviceUpdate(audio_io_handle_t audioIo,
+                                                      audio_port_handle_t deviceId) {
+    std::unique_lock<std::mutex> lock{mMutex};
+    ALOGD("%s  audioIo=%d deviceId=%d", __func__, audioIo, deviceId);
+    mAudioIo = audioIo;
+    mDeviceId = deviceId;
+    mCondition.notify_all();
+}
+
+status_t OnAudioDeviceUpdateNotifier::waitForAudioDeviceCb(audio_port_handle_t expDeviceId) {
+    std::unique_lock<std::mutex> lock{mMutex};
+    if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+        (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId)) {
+        mCondition.wait_for(lock, std::chrono::milliseconds(500));
+        if (mAudioIo == AUDIO_IO_HANDLE_NONE ||
+            (expDeviceId != AUDIO_PORT_HANDLE_NONE && expDeviceId != mDeviceId))
+            return TIMED_OUT;
+    }
+    return OK;
+}
+
+AudioPlayback::AudioPlayback(uint32_t sampleRate, audio_format_t format,
+                             audio_channel_mask_t channelMask, audio_output_flags_t flags,
+                             audio_session_t sessionId, AudioTrack::transfer_type transferType,
+                             audio_attributes_t* attributes, audio_offload_info_t* info)
+    : mSampleRate(sampleRate),
+      mFormat(format),
+      mChannelMask(channelMask),
+      mFlags(flags),
+      mSessionId(sessionId),
+      mTransferType(transferType),
+      mAttributes(attributes),
+      mOffloadInfo(info) {
+    mStopPlaying = false;
+    mBytesUsedSoFar = 0;
+    mState = PLAY_NO_INIT;
+    mMemCapacity = 0;
+    mMemoryDealer = nullptr;
+    mMemory = nullptr;
+}
+
+AudioPlayback::~AudioPlayback() {
+    stop();
+}
+
+status_t AudioPlayback::create() {
+    if (mState != PLAY_NO_INIT) return INVALID_OPERATION;
+    std::string packageName{"AudioPlayback"};
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = packageName;
+    attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+    attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+    attributionSource.token = sp<BBinder>::make();
+    if (mTransferType == AudioTrack::TRANSFER_OBTAIN) {
+        mTrack = new AudioTrack(attributionSource);
+        mTrack->set(AUDIO_STREAM_MUSIC, mSampleRate, mFormat, mChannelMask, 0 /* frameCount */,
+                    mFlags, nullptr /* callback */, 0 /* notificationFrames */,
+                    nullptr /* sharedBuffer */, false /*canCallJava */, mSessionId, mTransferType,
+                    mOffloadInfo, attributionSource, mAttributes);
+    } else if (mTransferType == AudioTrack::TRANSFER_SHARED) {
+        mTrack = new AudioTrack(AUDIO_STREAM_MUSIC, mSampleRate, mFormat, mChannelMask, mMemory,
+                                mFlags, wp<AudioTrack::IAudioTrackCallback>::fromExisting(this), 0,
+                                mSessionId, mTransferType, nullptr, attributionSource, mAttributes);
+    } else {
+        ALOGE("Test application is not handling transfer type %s",
+              AudioTrack::convertTransferToText(mTransferType));
+        return INVALID_OPERATION;
+    }
+    mTrack->setCallerName(packageName);
+    status_t status = mTrack->initCheck();
+    if (NO_ERROR == status) mState = PLAY_READY;
+    return status;
+}
+
+status_t AudioPlayback::loadResource(const char* name) {
+    status_t status = OK;
+    FILE* fp = fopen(name, "rbe");
+    struct stat buf {};
+    if (fp && !fstat(fileno(fp), &buf)) {
+        mMemCapacity = buf.st_size;
+        mMemoryDealer = new MemoryDealer(mMemCapacity, "AudioPlayback");
+        if (nullptr == mMemoryDealer.get()) {
+            ALOGE("couldn't get MemoryDealer!");
+            fclose(fp);
+            return NO_MEMORY;
+        }
+        mMemory = mMemoryDealer->allocate(mMemCapacity);
+        if (nullptr == mMemory.get()) {
+            ALOGE("couldn't get IMemory!");
+            fclose(fp);
+            return NO_MEMORY;
+        }
+        uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
+        fread(ipBuffer, sizeof(uint8_t), mMemCapacity, fp);
+    } else {
+        ALOGE("unable to open input file %s", name);
+        status = NAME_NOT_FOUND;
+    }
+    if (fp) fclose(fp);
+    return status;
+}
+
+sp<AudioTrack> AudioPlayback::getAudioTrackHandle() {
+    return (PLAY_NO_INIT != mState) ? mTrack : nullptr;
+}
+
+status_t AudioPlayback::start() {
+    status_t status;
+    if (PLAY_READY != mState) {
+        return INVALID_OPERATION;
+    } else {
+        status = mTrack->start();
+        if (OK == status) {
+            mState = PLAY_STARTED;
+            LOG_FATAL_IF(false != mTrack->stopped());
+        }
+    }
+    return status;
+}
+
+void AudioPlayback::onBufferEnd() {
+    std::unique_lock<std::mutex> lock{mMutex};
+    mStopPlaying = true;
+    mCondition.notify_all();
+}
+
+status_t AudioPlayback::fillBuffer() {
+    if (PLAY_STARTED != mState) return INVALID_OPERATION;
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
+    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mMemory->unsecurePointer()));
+    size_t nonContig = 0;
+    size_t bytesAvailable = mMemCapacity - mBytesUsedSoFar;
+    while (bytesAvailable > 0) {
+        AudioTrack::Buffer trackBuffer;
+        trackBuffer.frameCount = mTrack->frameCount() * 2;
+        status_t status = mTrack->obtainBuffer(&trackBuffer, 1, &nonContig);
+        if (OK == status) {
+            size_t bytesToCopy = std::min(bytesAvailable, trackBuffer.size());
+            if (bytesToCopy > 0) {
+                memcpy(trackBuffer.data(), ipBuffer + mBytesUsedSoFar, bytesToCopy);
+            }
+            mTrack->releaseBuffer(&trackBuffer);
+            mBytesUsedSoFar += bytesToCopy;
+            bytesAvailable = mMemCapacity - mBytesUsedSoFar;
+            counter = 0;
+        } else if (WOULD_BLOCK == status) {
+            // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+            if (counter == maxTries) return TIMED_OUT;
+            counter++;
+        }
+    }
+    return OK;
+}
+
+status_t AudioPlayback::waitForConsumption(bool testSeek) {
+    if (PLAY_STARTED != mState) return INVALID_OPERATION;
+
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
+    size_t totalFrameCount = mMemCapacity / mTrack->frameSize();
+    while (!mStopPlaying && counter < maxTries) {
+        uint32_t currPosition;
+        mTrack->getPosition(&currPosition);
+        if (currPosition >= totalFrameCount) counter++;
+
+        if (testSeek && (currPosition > totalFrameCount * 0.6)) {
+            testSeek = false;
+            if (!mTrack->hasStarted()) return BAD_VALUE;
+            mTrack->pauseAndWait(std::chrono::seconds(2));
+            if (mTrack->hasStarted()) return BAD_VALUE;
+            mTrack->reload();
+            mTrack->getPosition(&currPosition);
+            if (currPosition != 0) return BAD_VALUE;
+            mTrack->start();
+            while (currPosition < totalFrameCount * 0.3) {
+                mTrack->getPosition(&currPosition);
+            }
+            mTrack->pauseAndWait(std::chrono::seconds(2));
+            uint32_t setPosition = totalFrameCount * 0.9;
+            mTrack->setPosition(setPosition);
+            uint32_t bufferPosition;
+            mTrack->getBufferPosition(&bufferPosition);
+            if (bufferPosition != setPosition) return BAD_VALUE;
+            mTrack->start();
+        }
+        std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_PERIOD_MS));
+    }
+    if (!mStopPlaying && counter == maxTries) return TIMED_OUT;
+    return OK;
+}
+
+status_t AudioPlayback::onProcess(bool testSeek) {
+    if (mTransferType == AudioTrack::TRANSFER_SHARED)
+        return waitForConsumption(testSeek);
+    else if (mTransferType == AudioTrack::TRANSFER_OBTAIN)
+        return fillBuffer();
+    else
+        return INVALID_OPERATION;
+}
+
+void AudioPlayback::stop() {
+    std::unique_lock<std::mutex> lock{mMutex};
+    mStopPlaying = true;
+    if (mState != PLAY_STOPPED && mState != PLAY_NO_INIT) {
+        int32_t msec = 0;
+        (void)mTrack->pendingDuration(&msec);
+        mTrack->stopAndJoinCallbacks();
+        LOG_FATAL_IF(true != mTrack->stopped());
+        mState = PLAY_STOPPED;
+        if (msec > 0) {
+            ALOGD("deleting recycled track, waiting for data drain (%d msec)", msec);
+            usleep(msec * 1000LL);
+        }
+    }
+}
+
+// hold pcm data sent by AudioRecord
+RawBuffer::RawBuffer(int64_t ptsPipeline, int64_t ptsManual, int32_t capacity)
+    : mData(capacity > 0 ? new uint8_t[capacity] : nullptr),
+      mPtsPipeline(ptsPipeline),
+      mPtsManual(ptsManual),
+      mCapacity(capacity) {}
+
+// Simple AudioCapture
+size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {
+    if (mState != REC_STARTED) {
+        ALOGE("Unexpected Callback from audiorecord, not reading data");
+        return 0;
+    }
+
+    // no more frames to read
+    if (mNumFramesReceived >= mNumFramesToRecord || mStopRecording) {
+        mStopRecording = true;
+        return 0;
+    }
+
+    int64_t timeUs = 0, position = 0, timeNs = 0;
+    ExtendedTimestamp ts;
+    ExtendedTimestamp::Location location;
+    const int32_t usPerSec = 1000000;
+
+    if (mRecord->getTimestamp(&ts) == OK &&
+        ts.getBestTimestamp(&position, &timeNs, ExtendedTimestamp::TIMEBASE_MONOTONIC, &location) ==
+                OK) {
+        // Use audio timestamp.
+        timeUs = timeNs / 1000 -
+                 (position - mNumFramesReceived + mNumFramesLost) * usPerSec / mSampleRate;
+    } else {
+        // This should not happen in normal case.
+        ALOGW("Failed to get audio timestamp, fallback to use systemclock");
+        timeUs = systemTime() / 1000LL;
+        // Estimate the real sampling time of the 1st sample in this buffer
+        // from AudioRecord's latency. (Apply this adjustment first so that
+        // the start time logic is not affected.)
+        timeUs -= mRecord->latency() * 1000LL;
+    }
+
+    ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
+
+    const size_t frameSize = mRecord->frameSize();
+    uint64_t numLostBytes = (uint64_t)mRecord->getInputFramesLost() * frameSize;
+    if (numLostBytes > 0) {
+        ALOGW("Lost audio record data: %" PRIu64 " bytes", numLostBytes);
+    }
+    std::deque<RawBuffer> tmpQueue;
+    while (numLostBytes > 0) {
+        uint64_t bufferSize = numLostBytes;
+        if (numLostBytes > mMaxBytesPerCallback) {
+            numLostBytes -= mMaxBytesPerCallback;
+            bufferSize = mMaxBytesPerCallback;
+        } else {
+            numLostBytes = 0;
+        }
+        const int64_t timestampUs =
+                ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+                mRecord->getSampleRate();
+        RawBuffer emptyBuffer{timeUs, timestampUs, static_cast<int32_t>(bufferSize)};
+        memset(emptyBuffer.mData.get(), 0, bufferSize);
+        mNumFramesLost += bufferSize / frameSize;
+        mNumFramesReceived += bufferSize / frameSize;
+        tmpQueue.push_back(std::move(emptyBuffer));
+    }
+
+    if (buffer.size() == 0) {
+        ALOGW("Nothing is available from AudioRecord callback buffer");
+    } else {
+        const size_t bufferSize = buffer.size();
+        const int64_t timestampUs =
+                ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+                mRecord->getSampleRate();
+        RawBuffer audioBuffer{timeUs, timestampUs, static_cast<int32_t>(bufferSize)};
+        memcpy(audioBuffer.mData.get(), buffer.data(), bufferSize);
+        mNumFramesReceived += bufferSize / frameSize;
+        tmpQueue.push_back(std::move(audioBuffer));
+    }
+
+    if (tmpQueue.size() > 0) {
+        std::unique_lock<std::mutex> lock{mMutex};
+        for (auto it = tmpQueue.begin(); it != tmpQueue.end(); it++)
+            mBuffersReceived.push_back(std::move(*it));
+        mCondition.notify_all();
+    }
+    return buffer.size();
+}
+
+void AudioCapture::onOverrun() {
+    ALOGV("received event overrun");
+    mBufferOverrun = true;
+}
+
+void AudioCapture::onMarker(uint32_t markerPosition) {
+    ALOGV("received Callback at position %d", markerPosition);
+    mReceivedCbMarkerAtPosition = markerPosition;
+}
+
+void AudioCapture::onNewPos(uint32_t markerPosition) {
+    ALOGV("received Callback at position %d", markerPosition);
+    mReceivedCbMarkerCount++;
+}
+
+void AudioCapture::onNewIAudioRecord() {
+    ALOGV("IAudioRecord is re-created");
+}
+
+AudioCapture::AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
+                           audio_channel_mask_t channelMask, audio_input_flags_t flags,
+                           audio_session_t sessionId, AudioRecord::transfer_type transferType,
+                           const audio_attributes_t* attributes)
+    : mInputSource(inputSource),
+      mSampleRate(sampleRate),
+      mFormat(format),
+      mChannelMask(channelMask),
+      mFlags(flags),
+      mSessionId(sessionId),
+      mTransferType(transferType),
+      mAttributes(attributes) {
+    mFrameCount = 0;
+    mNotificationFrames = 0;
+    mNumFramesToRecord = 0;
+    mNumFramesReceived = 0;
+    mNumFramesLost = 0;
+    mBufferOverrun = false;
+    mMarkerPosition = 0;
+    mMarkerPeriod = 0;
+    mReceivedCbMarkerAtPosition = -1;
+    mReceivedCbMarkerCount = 0;
+    mState = REC_NO_INIT;
+    mStopRecording = false;
+}
+
+AudioCapture::~AudioCapture() {
+    if (mOutFileFd > 0) close(mOutFileFd);
+    stop();
+}
+
+status_t AudioCapture::create() {
+    if (mState != REC_NO_INIT) return INVALID_OPERATION;
+    // get Min Frame Count
+    size_t minFrameCount;
+    status_t status =
+            AudioRecord::getMinFrameCount(&minFrameCount, mSampleRate, mFormat, mChannelMask);
+    if (NO_ERROR != status) return status;
+    // Limit notificationFrames basing on client bufferSize
+    const int samplesPerFrame = audio_channel_count_from_in_mask(mChannelMask);
+    const int bytesPerSample = audio_bytes_per_sample(mFormat);
+    mNotificationFrames = mMaxBytesPerCallback / (samplesPerFrame * bytesPerSample);
+    // select frameCount to be at least minFrameCount
+    mFrameCount = 2 * mNotificationFrames;
+    while (mFrameCount < minFrameCount) {
+        mFrameCount += mNotificationFrames;
+    }
+    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+        ALOGW("Overriding all previous computations");
+        mFrameCount = 0;
+        mNotificationFrames = 0;
+    }
+    mNumFramesToRecord = (mSampleRate * 0.25);  // record .25 sec
+    std::string packageName{"AudioCapture"};
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = packageName;
+    attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+    attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+    attributionSource.token = sp<BBinder>::make();
+    if (mTransferType == AudioRecord::TRANSFER_OBTAIN) {
+        if (mSampleRate == 48000) {  // test all available constructors
+            mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
+                                      attributionSource, mFrameCount, nullptr /* callback */,
+                                      mNotificationFrames, mSessionId, mTransferType, mFlags,
+                                      mAttributes);
+        } else {
+            mRecord = new AudioRecord(attributionSource);
+            status = mRecord->set(mInputSource, mSampleRate, mFormat, mChannelMask, mFrameCount,
+                                  nullptr /* callback */, 0 /* notificationFrames */,
+                                  false /* canCallJava */, mSessionId, mTransferType, mFlags,
+                                  attributionSource.uid, attributionSource.pid, mAttributes);
+        }
+        if (NO_ERROR != status) return status;
+    } else if (mTransferType == AudioRecord::TRANSFER_CALLBACK) {
+        mRecord = new AudioRecord(mInputSource, mSampleRate, mFormat, mChannelMask,
+                                  attributionSource, mFrameCount, this, mNotificationFrames,
+                                  mSessionId, mTransferType, mFlags, mAttributes);
+    } else {
+        ALOGE("Test application is not handling transfer type %s",
+              AudioRecord::convertTransferToText(mTransferType));
+        return NO_INIT;
+    }
+    mRecord->setCallerName(packageName);
+    status = mRecord->initCheck();
+    if (NO_ERROR == status) mState = REC_READY;
+    if (mFlags & AUDIO_INPUT_FLAG_FAST) {
+        mFrameCount = mRecord->frameCount();
+        mNotificationFrames = mRecord->getNotificationPeriodInFrames();
+        mMaxBytesPerCallback = mNotificationFrames * samplesPerFrame * bytesPerSample;
+    }
+    return status;
+}
+
+status_t AudioCapture::setRecordDuration(float durationInSec) {
+    if (REC_READY != mState) {
+        return INVALID_OPERATION;
+    }
+    uint32_t sampleRate = mSampleRate == 0 ? mRecord->getSampleRate() : mSampleRate;
+    mNumFramesToRecord = (sampleRate * durationInSec);
+    return OK;
+}
+
+status_t AudioCapture::enableRecordDump() {
+    if (mOutFileFd != -1) {
+        return INVALID_OPERATION;
+    }
+    TemporaryFile tf("/data/local/tmp");
+    tf.DoNotRemove();
+    mOutFileFd = tf.release();
+    mFileName = std::string{tf.path};
+    return OK;
+}
+
+sp<AudioRecord> AudioCapture::getAudioRecordHandle() {
+    return (REC_NO_INIT == mState) ? nullptr : mRecord;
+}
+
+status_t AudioCapture::start(AudioSystem::sync_event_t event, audio_session_t triggerSession) {
+    status_t status;
+    if (REC_READY != mState) {
+        return INVALID_OPERATION;
+    } else {
+        status = mRecord->start(event, triggerSession);
+        if (OK == status) {
+            mState = REC_STARTED;
+            LOG_FATAL_IF(false != mRecord->stopped());
+        }
+    }
+    return status;
+}
+
+status_t AudioCapture::stop() {
+    status_t status = OK;
+    mStopRecording = true;
+    if (mState != REC_STOPPED && mState != REC_NO_INIT) {
+        if (mInputSource != AUDIO_SOURCE_DEFAULT) {
+            bool state = false;
+            status = AudioSystem::isSourceActive(mInputSource, &state);
+            if (status == OK && !state) status = BAD_VALUE;
+        }
+        mRecord->stopAndJoinCallbacks();
+        mState = REC_STOPPED;
+        LOG_FATAL_IF(true != mRecord->stopped());
+    }
+    return status;
+}
+
+status_t AudioCapture::obtainBuffer(RawBuffer& buffer) {
+    if (REC_STARTED != mState) return INVALID_OPERATION;
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
+    size_t nonContig = 0;
+    while (mNumFramesReceived < mNumFramesToRecord) {
+        AudioRecord::Buffer recordBuffer;
+        recordBuffer.frameCount = mNotificationFrames;
+        status_t status = mRecord->obtainBuffer(&recordBuffer, 1, &nonContig);
+        if (OK == status) {
+            const int64_t timestampUs =
+                    ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
+                    mRecord->getSampleRate();
+            RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
+            memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
+            buffer = std::move(buff);
+            mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
+            mRecord->releaseBuffer(&recordBuffer);
+            counter = 0;
+        } else if (WOULD_BLOCK == status) {
+            // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
+            if (counter == maxTries) return TIMED_OUT;
+            counter++;
+        }
+    }
+    return OK;
+}
+
+status_t AudioCapture::obtainBufferCb(RawBuffer& buffer) {
+    if (REC_STARTED != mState) return INVALID_OPERATION;
+    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
+    int counter = 0;
+    std::unique_lock<std::mutex> lock{mMutex};
+    while (mBuffersReceived.empty() && !mStopRecording && counter < maxTries) {
+        mCondition.wait_for(lock, std::chrono::milliseconds(WAIT_PERIOD_MS));
+        counter++;
+    }
+    if (!mBuffersReceived.empty()) {
+        auto it = mBuffersReceived.begin();
+        buffer = std::move(*it);
+        mBuffersReceived.erase(it);
+    } else {
+        if (!mStopRecording && counter == maxTries) return TIMED_OUT;
+    }
+    return OK;
+}
+
+status_t AudioCapture::audioProcess() {
+    RawBuffer buffer;
+    status_t status = OK;
+    while (mNumFramesReceived < mNumFramesToRecord && status == OK) {
+        if (mTransferType == AudioRecord::TRANSFER_CALLBACK)
+            status = obtainBufferCb(buffer);
+        else
+            status = obtainBuffer(buffer);
+        if (OK == status && mOutFileFd > 0) {
+            const char* ptr = static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
+            write(mOutFileFd, ptr, buffer.mCapacity);
+        }
+    }
+    return OK;
+}
+
+status_t listAudioPorts(std::vector<audio_port_v7>& portsVec) {
+    int attempts = 5;
+    status_t status;
+    unsigned int generation1, generation;
+    unsigned int numPorts = 0;
+    do {
+        if (attempts-- < 0) {
+            status = TIMED_OUT;
+            break;
+        }
+        status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
+                                             nullptr, &generation1);
+        if (status != NO_ERROR) {
+            ALOGE("AudioSystem::listAudioPorts returned error %d", status);
+            break;
+        }
+        portsVec.resize(numPorts);
+        status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts,
+                                             portsVec.data(), &generation);
+    } while (generation1 != generation && status == NO_ERROR);
+    if (status != NO_ERROR) {
+        numPorts = 0;
+        portsVec.clear();
+    }
+    return status;
+}
+
+status_t getPortById(const audio_port_handle_t portId, audio_port_v7& port) {
+    std::vector<struct audio_port_v7> ports;
+    status_t status = listAudioPorts(ports);
+    if (status != OK) return status;
+    for (auto i = 0; i < ports.size(); i++) {
+        if (ports[i].id == portId) {
+            port = ports[i];
+            return OK;
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
+                             audio_devices_t deviceType, const std::string& address,
+                             audio_port_v7& port) {
+    std::vector<struct audio_port_v7> ports;
+    status_t status = listAudioPorts(ports);
+    if (status != OK) return status;
+    for (auto i = 0; i < ports.size(); i++) {
+        if (ports[i].role == role && ports[i].type == type &&
+            ports[i].ext.device.type == deviceType &&
+            !strncmp(ports[i].ext.device.address, address.c_str(), AUDIO_DEVICE_MAX_ADDRESS_LEN)) {
+            port = ports[i];
+            return OK;
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec) {
+    int attempts = 5;
+    status_t status;
+    unsigned int generation1, generation;
+    unsigned int numPatches = 0;
+    do {
+        if (attempts-- < 0) {
+            status = TIMED_OUT;
+            break;
+        }
+        status = AudioSystem::listAudioPatches(&numPatches, nullptr, &generation1);
+        if (status != NO_ERROR) {
+            ALOGE("AudioSystem::listAudioPatches returned error %d", status);
+            break;
+        }
+        patchesVec.resize(numPatches);
+        status = AudioSystem::listAudioPatches(&numPatches, patchesVec.data(), &generation);
+    } while (generation1 != generation && status == NO_ERROR);
+    if (status != NO_ERROR) {
+        numPatches = 0;
+        patchesVec.clear();
+    }
+    return status;
+}
+
+status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch) {
+    std::vector<struct audio_patch> patches;
+    status_t status = listAudioPatches(patches);
+    if (status != OK) return status;
+
+    for (auto i = 0; i < patches.size(); i++) {
+        for (auto j = 0; j < patches[i].num_sources; j++) {
+            if (patches[i].sources[j].type == AUDIO_PORT_TYPE_MIX &&
+                patches[i].sources[j].ext.mix.handle == audioIo) {
+                patch = patches[i];
+                return OK;
+            }
+        }
+    }
+    return BAD_VALUE;
+}
+
+status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch) {
+    std::vector<struct audio_patch> patches;
+    status_t status = listAudioPatches(patches);
+    if (status != OK) return status;
+
+    for (auto i = 0; i < patches.size(); i++) {
+        for (auto j = 0; j < patches[i].num_sinks; j++) {
+            if (patches[i].sinks[j].type == AUDIO_PORT_TYPE_MIX &&
+                patches[i].sinks[j].ext.mix.handle == audioIo) {
+                patch = patches[i];
+                return OK;
+            }
+        }
+    }
+    return BAD_VALUE;
+}
+
+bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch) {
+    for (auto j = 0; j < patch.num_sinks; j++) {
+        if (patch.sinks[j].type == AUDIO_PORT_TYPE_DEVICE && patch.sinks[j].id == deviceId) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool patchContainsInputDevice(audio_port_handle_t deviceId, audio_patch patch) {
+    for (auto j = 0; j < patch.num_sources; j++) {
+        if (patch.sources[j].type == AUDIO_PORT_TYPE_DEVICE && patch.sources[j].id == deviceId) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool checkPatchPlayback(audio_io_handle_t audioIo, audio_port_handle_t deviceId) {
+    struct audio_patch patch;
+    if (getPatchForOutputMix(audioIo, patch) == OK) {
+        return patchContainsOutputDevice(deviceId, patch);
+    }
+    return false;
+}
+
+bool checkPatchCapture(audio_io_handle_t audioIo, audio_port_handle_t deviceId) {
+    struct audio_patch patch;
+    if (getPatchForInputMix(audioIo, patch) == OK) {
+        return patchContainsInputDevice(deviceId, patch);
+    }
+    return false;
+}
+
+std::string dumpPortConfig(const audio_port_config& port) {
+    std::ostringstream result;
+    std::string deviceInfo;
+    if (port.type == AUDIO_PORT_TYPE_DEVICE) {
+        if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
+            InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+        } else {
+            OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+        }
+        deviceInfo += std::string(", address = ") + port.ext.device.address;
+    }
+    result << "audio_port_handle_t = " << port.id << ", "
+           << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
+           << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
+           << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
+           << "config_mask = 0x" << std::hex << port.config_mask << std::dec << ", ";
+    if (port.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
+        result << "sample rate = " << port.sample_rate << ", ";
+    }
+    if (port.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
+        result << "channel mask = " << port.channel_mask << ", ";
+    }
+    if (port.config_mask & AUDIO_PORT_CONFIG_FORMAT) {
+        result << "format = " << port.format << ", ";
+    }
+    result << "input flags = " << port.flags.input << ", ";
+    result << "output flags = " << port.flags.output << ", ";
+    result << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
+           << "\n";
+    return result.str();
+}
+
+std::string dumpPatch(const audio_patch& patch) {
+    std::ostringstream result;
+    result << "----------------- Dumping Patch ------------ \n";
+    result << "Patch Handle: " << patch.id << ", sources: " << patch.num_sources
+           << ", sink: " << patch.num_sinks << "\n";
+    audio_port_v7 port;
+    for (uint32_t i = 0; i < patch.num_sources; i++) {
+        result << "----------------- Dumping Source Port Config @ index " << i
+               << " ------------ \n";
+        result << dumpPortConfig(patch.sources[i]);
+        result << "----------------- Dumping Source Port for id " << patch.sources[i].id
+               << " ------------ \n";
+        getPortById(patch.sources[i].id, port);
+        result << dumpPort(port);
+    }
+    for (uint32_t i = 0; i < patch.num_sinks; i++) {
+        result << "----------------- Dumping Sink Port Config @ index " << i << " ------------ \n";
+        result << dumpPortConfig(patch.sinks[i]);
+        result << "----------------- Dumping Sink Port for id " << patch.sinks[i].id
+               << " ------------ \n";
+        getPortById(patch.sinks[i].id, port);
+        result << dumpPort(port);
+    }
+    return result.str();
+}
+
+std::string dumpPort(const audio_port_v7& port) {
+    std::ostringstream result;
+    std::string deviceInfo;
+    if (port.type == AUDIO_PORT_TYPE_DEVICE) {
+        if (port.ext.device.type & AUDIO_DEVICE_BIT_IN) {
+            InputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+        } else {
+            OutputDeviceConverter::maskToString(port.ext.device.type, deviceInfo);
+        }
+        deviceInfo += std::string(", address = ") + port.ext.device.address;
+    }
+    result << "audio_port_handle_t = " << port.id << ", "
+           << "Role = " << (port.role == AUDIO_PORT_ROLE_SOURCE ? "source" : "sink") << ", "
+           << "Type = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix") << ", "
+           << "deviceInfo = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? deviceInfo : "") << ", "
+           << "Name = " << port.name << ", "
+           << "num profiles = " << port.num_audio_profiles << ", "
+           << "mix io handle = " << (port.type == AUDIO_PORT_TYPE_DEVICE ? 0 : port.ext.mix.handle)
+           << ", ";
+    for (int i = 0; i < port.num_audio_profiles; i++) {
+        result << "AudioProfile = " << i << " {";
+        result << "format = " << port.audio_profiles[i].format << ", ";
+        result << "samplerates = ";
+        for (int j = 0; j < port.audio_profiles[i].num_sample_rates; j++) {
+            result << port.audio_profiles[i].sample_rates[j] << ", ";
+        }
+        result << "channelmasks = ";
+        for (int j = 0; j < port.audio_profiles[i].num_channel_masks; j++) {
+            result << "0x" << std::hex << port.audio_profiles[i].channel_masks[j] << std::dec
+                   << ", ";
+        }
+        result << "} ";
+    }
+    result << dumpPortConfig(port.active_config);
+    return result.str();
+}
+
+std::string getXmlAttribute(const xmlNode* cur, const char* attribute) {
+    auto charPtr = make_xmlUnique(xmlGetProp(cur, reinterpret_cast<const xmlChar*>(attribute)));
+    if (charPtr == NULL) {
+        return "";
+    }
+    std::string value(reinterpret_cast<const char*>(charPtr.get()));
+    return value;
+}
+
+status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
+                                              std::vector<MixPort>& mixPorts,
+                                              std::vector<Route>& routes) {
+    std::string path = audio_find_readable_configuration_file("audio_policy_configuration.xml");
+    if (path.length() == 0) return UNKNOWN_ERROR;
+    auto doc = make_xmlUnique(xmlParseFile(path.c_str()));
+    if (doc == nullptr) return UNKNOWN_ERROR;
+    xmlNode* root = xmlDocGetRootElement(doc.get());
+    if (root == nullptr) return UNKNOWN_ERROR;
+    if (xmlXIncludeProcess(doc.get()) < 0) return UNKNOWN_ERROR;
+    mixPorts.clear();
+    if (!xmlStrcmp(root->name, reinterpret_cast<const xmlChar*>("audioPolicyConfiguration"))) {
+        std::string raw{getXmlAttribute(root, "version")};
+        for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
+            if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("modules"))) {
+                xmlNode* root = child;
+                for (auto* child = root->xmlChildrenNode; child != nullptr; child = child->next) {
+                    if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>("module"))) {
+                        xmlNode* root = child;
+                        for (auto* child = root->xmlChildrenNode; child != nullptr;
+                             child = child->next) {
+                            if (!xmlStrcmp(child->name,
+                                           reinterpret_cast<const xmlChar*>("mixPorts"))) {
+                                xmlNode* root = child;
+                                for (auto* child = root->xmlChildrenNode; child != nullptr;
+                                     child = child->next) {
+                                    if (!xmlStrcmp(child->name,
+                                                   reinterpret_cast<const xmlChar*>("mixPort"))) {
+                                        MixPort mixPort;
+                                        xmlNode* root = child;
+                                        mixPort.name = getXmlAttribute(root, "name");
+                                        mixPort.role = getXmlAttribute(root, "role");
+                                        mixPort.flags = getXmlAttribute(root, "flags");
+                                        if (mixPort.role == "source") mixPorts.push_back(mixPort);
+                                    }
+                                }
+                            } else if (!xmlStrcmp(child->name, reinterpret_cast<const xmlChar*>(
+                                                                       "attachedDevices"))) {
+                                xmlNode* root = child;
+                                for (auto* child = root->xmlChildrenNode; child != nullptr;
+                                     child = child->next) {
+                                    if (!xmlStrcmp(child->name,
+                                                   reinterpret_cast<const xmlChar*>("item"))) {
+                                        auto xmlValue = make_xmlUnique(xmlNodeListGetString(
+                                                child->doc, child->xmlChildrenNode, 1));
+                                        if (xmlValue == nullptr) {
+                                            raw = "";
+                                        } else {
+                                            raw = reinterpret_cast<const char*>(xmlValue.get());
+                                        }
+                                        std::string& value = raw;
+                                        attachedDevices.push_back(std::move(value));
+                                    }
+                                }
+                            } else if (!xmlStrcmp(child->name,
+                                                  reinterpret_cast<const xmlChar*>("routes"))) {
+                                xmlNode* root = child;
+                                for (auto* child = root->xmlChildrenNode; child != nullptr;
+                                     child = child->next) {
+                                    if (!xmlStrcmp(child->name,
+                                                   reinterpret_cast<const xmlChar*>("route"))) {
+                                        Route route;
+                                        xmlNode* root = child;
+                                        route.name = getXmlAttribute(root, "name");
+                                        route.sources = getXmlAttribute(root, "sources");
+                                        route.sink = getXmlAttribute(root, "sink");
+                                        routes.push_back(route);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return OK;
+}
diff --git a/media/libaudioclient/tests/audio_test_utils.h b/media/libaudioclient/tests/audio_test_utils.h
new file mode 100644
index 0000000..90c30c2
--- /dev/null
+++ b/media/libaudioclient/tests/audio_test_utils.h
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+#ifndef AUDIO_TEST_UTILS_H_
+#define AUDIO_TEST_UTILS_H_
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <atomic>
+#include <chrono>
+#include <cinttypes>
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <thread>
+
+#include <binder/MemoryDealer.h>
+#include <libxml/parser.h>
+#include <libxml/xinclude.h>
+#include <media/AidlConversion.h>
+#include <media/AudioRecord.h>
+#include <media/AudioTrack.h>
+
+using namespace android;
+
+struct MixPort {
+    std::string name;
+    std::string role;
+    std::string flags;
+};
+
+struct Route {
+    std::string name;
+    std::string sources;
+    std::string sink;
+};
+
+status_t parse_audio_policy_configuration_xml(std::vector<std::string>& attachedDevices,
+                                              std::vector<MixPort>& mixPorts,
+                                              std::vector<Route>& routes);
+status_t listAudioPorts(std::vector<audio_port_v7>& portsVec);
+status_t listAudioPatches(std::vector<struct audio_patch>& patchesVec);
+status_t getPortByAttributes(audio_port_role_t role, audio_port_type_t type,
+                             audio_devices_t deviceType, const std::string& address,
+                             audio_port_v7& port);
+status_t getPatchForOutputMix(audio_io_handle_t audioIo, audio_patch& patch);
+status_t getPatchForInputMix(audio_io_handle_t audioIo, audio_patch& patch);
+bool patchContainsOutputDevice(audio_port_handle_t deviceId, audio_patch patch);
+bool patchContainsInputDevice(audio_port_handle_t deviceId, audio_patch patch);
+bool checkPatchPlayback(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
+bool checkPatchCapture(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
+std::string dumpPort(const audio_port_v7& port);
+std::string dumpPortConfig(const audio_port_config& port);
+std::string dumpPatch(const audio_patch& patch);
+
+class OnAudioDeviceUpdateNotifier : public AudioSystem::AudioDeviceCallback {
+  public:
+    audio_io_handle_t mAudioIo = AUDIO_IO_HANDLE_NONE;
+    audio_port_handle_t mDeviceId = AUDIO_PORT_HANDLE_NONE;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+
+    void onAudioDeviceUpdate(audio_io_handle_t audioIo, audio_port_handle_t deviceId);
+    status_t waitForAudioDeviceCb(audio_port_handle_t expDeviceId = AUDIO_PORT_HANDLE_NONE);
+};
+
+// Simple AudioPlayback class.
+class AudioPlayback : public AudioTrack::IAudioTrackCallback {
+    friend sp<AudioPlayback>;
+    AudioPlayback(uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask,
+                  audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
+                  audio_session_t sessionId = AUDIO_SESSION_NONE,
+                  AudioTrack::transfer_type transferType = AudioTrack::TRANSFER_SHARED,
+                  audio_attributes_t* attributes = nullptr, audio_offload_info_t* info = nullptr);
+
+  public:
+    status_t loadResource(const char* name);
+    status_t create();
+    sp<AudioTrack> getAudioTrackHandle();
+    status_t start();
+    status_t waitForConsumption(bool testSeek = false);
+    status_t fillBuffer();
+    status_t onProcess(bool testSeek = false);
+    virtual void onBufferEnd() override;
+    void stop();
+
+    bool mStopPlaying;
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+
+    enum State {
+        PLAY_NO_INIT,
+        PLAY_READY,
+        PLAY_STARTED,
+        PLAY_STOPPED,
+    };
+
+  private:
+    ~AudioPlayback();
+    const uint32_t mSampleRate;
+    const audio_format_t mFormat;
+    const audio_channel_mask_t mChannelMask;
+    const audio_output_flags_t mFlags;
+    const audio_session_t mSessionId;
+    const AudioTrack::transfer_type mTransferType;
+    const audio_attributes_t* mAttributes;
+    const audio_offload_info_t* mOffloadInfo;
+
+    size_t mBytesUsedSoFar;
+    State mState;
+    size_t mMemCapacity;
+    sp<MemoryDealer> mMemoryDealer;
+    sp<IMemory> mMemory;
+
+    sp<AudioTrack> mTrack;
+};
+
+// hold pcm data sent by AudioRecord
+class RawBuffer {
+  public:
+    RawBuffer(int64_t ptsPipeline = -1, int64_t ptsManual = -1, int32_t capacity = 0);
+
+    std::unique_ptr<uint8_t[]> mData;
+    int64_t mPtsPipeline;
+    int64_t mPtsManual;
+    int32_t mCapacity;
+};
+
+// Simple AudioCapture
+class AudioCapture : public AudioRecord::IAudioRecordCallback {
+  public:
+    AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audio_format_t format,
+                 audio_channel_mask_t channelMask,
+                 audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE,
+                 audio_session_t sessionId = AUDIO_SESSION_ALLOCATE,
+                 AudioRecord::transfer_type transferType = AudioRecord::TRANSFER_CALLBACK,
+                 const audio_attributes_t* attributes = nullptr);
+    ~AudioCapture();
+    size_t onMoreData(const AudioRecord::Buffer& buffer) override;
+    void onOverrun() override;
+    void onMarker(uint32_t markerPosition) override;
+    void onNewPos(uint32_t newPos) override;
+    void onNewIAudioRecord() override;
+    status_t create();
+    status_t setRecordDuration(float durationInSec);
+    status_t enableRecordDump();
+    std::string getRecordDumpFileName() const { return mFileName; }
+    sp<AudioRecord> getAudioRecordHandle();
+    status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+                   audio_session_t triggerSession = AUDIO_SESSION_NONE);
+    status_t obtainBufferCb(RawBuffer& buffer);
+    status_t obtainBuffer(RawBuffer& buffer);
+    status_t audioProcess();
+    status_t stop();
+
+    uint32_t mFrameCount;
+    uint32_t mNotificationFrames;
+    int64_t mNumFramesToRecord;
+    int64_t mNumFramesReceived;
+    int64_t mNumFramesLost;
+    uint32_t mMarkerPosition;
+    uint32_t mMarkerPeriod;
+    uint32_t mReceivedCbMarkerAtPosition;
+    uint32_t mReceivedCbMarkerCount;
+    bool mBufferOverrun;
+
+    enum State {
+        REC_NO_INIT,
+        REC_READY,
+        REC_STARTED,
+        REC_STOPPED,
+    };
+
+  private:
+    const audio_source_t mInputSource;
+    const uint32_t mSampleRate;
+    const audio_format_t mFormat;
+    const audio_channel_mask_t mChannelMask;
+    const audio_input_flags_t mFlags;
+    const audio_session_t mSessionId;
+    const AudioRecord::transfer_type mTransferType;
+    const audio_attributes_t* mAttributes;
+
+    size_t mMaxBytesPerCallback = 2048;
+    sp<AudioRecord> mRecord;
+    State mState;
+    bool mStopRecording;
+    std::string mFileName;
+    int mOutFileFd = -1;
+
+    std::mutex mMutex;
+    std::condition_variable mCondition;
+    std::deque<RawBuffer> mBuffersReceived;
+};
+
+#endif  // AUDIO_TEST_UTILS_H_
diff --git a/media/libaudioclient/tests/audioclient_serialization_tests.cpp b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
new file mode 100644
index 0000000..ef8500b
--- /dev/null
+++ b/media/libaudioclient/tests/audioclient_serialization_tests.cpp
@@ -0,0 +1,311 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioClientSerializationUnitTests"
+
+#include <cstdint>
+#include <cstdlib>
+#include <ctime>
+
+#include <gtest/gtest.h>
+
+#include <android_audio_policy_configuration_V7_0-enums.h>
+#include <xsdc/XsdcSupport.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+namespace xsd {
+using namespace ::android::audio::policy::configuration::V7_0;
+}
+
+template <typename T, typename X, typename FUNC>
+std::vector<T> getFlags(const xsdc_enum_range<X>& range, const FUNC& func,
+                        const std::string& findString = {}) {
+    std::vector<T> vec;
+    for (const auto& xsdEnumVal : range) {
+        T enumVal;
+        std::string enumString = toString(xsdEnumVal);
+        if (enumString.find(findString) != std::string::npos &&
+            func(enumString.c_str(), &enumVal)) {
+            vec.push_back(enumVal);
+        }
+    }
+    return vec;
+}
+
+static const std::vector<audio_usage_t> kUsages =
+        getFlags<audio_usage_t, xsd::AudioUsage, decltype(audio_usage_from_string)>(
+                xsdc_enum_range<xsd::AudioUsage>{}, audio_usage_from_string);
+
+static const std::vector<audio_content_type_t> kContentType =
+        getFlags<audio_content_type_t, xsd::AudioContentType,
+                 decltype(audio_content_type_from_string)>(xsdc_enum_range<xsd::AudioContentType>{},
+                                                           audio_content_type_from_string);
+
+static const std::vector<audio_source_t> kInputSources =
+        getFlags<audio_source_t, xsd::AudioSource, decltype(audio_source_from_string)>(
+                xsdc_enum_range<xsd::AudioSource>{}, audio_source_from_string);
+
+static const std::vector<audio_stream_type_t> kStreamtypes =
+        getFlags<audio_stream_type_t, xsd::AudioStreamType,
+                 decltype(audio_stream_type_from_string)>(xsdc_enum_range<xsd::AudioStreamType>{},
+                                                          audio_stream_type_from_string);
+
+static const std::vector<uint32_t> kMixMatchRules = {
+        RULE_MATCH_ATTRIBUTE_USAGE,
+        RULE_EXCLUDE_ATTRIBUTE_USAGE,
+        RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET,
+        RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET,
+        RULE_MATCH_UID,
+        RULE_EXCLUDE_UID,
+        RULE_MATCH_USERID,
+        RULE_EXCLUDE_USERID,
+};
+
+// Generates a random string.
+std::string CreateRandomString(size_t n) {
+    std::string data =
+            "abcdefghijklmnopqrstuvwxyz"
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+            "0123456789";
+    srand(static_cast<unsigned int>(time(0)));
+    std::string s(n, ' ');
+    for (size_t i = 0; i < n; ++i) {
+        s[i] = data[rand() % data.size()];
+    }
+    return s;
+}
+
+class FillAudioAttributes {
+  public:
+    void fillAudioAttributes(audio_attributes_t& attr);
+
+    unsigned int mSeed;
+};
+
+void FillAudioAttributes::fillAudioAttributes(audio_attributes_t& attr) {
+    attr.content_type = kContentType[rand() % kContentType.size()];
+    attr.usage = kUsages[rand() % kUsages.size()];
+    attr.source = kInputSources[rand() % kInputSources.size()];
+    // attr.flags -> [0, (1 << (CAPTURE_PRIVATE + 1) - 1)]
+    attr.flags = static_cast<audio_flags_mask_t>(rand() & 0x3fff);
+    sprintf(attr.tags, "%s",
+            CreateRandomString((int)rand() % (AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1)).c_str());
+}
+
+class SerializationTest : public FillAudioAttributes, public ::testing::Test {
+    void SetUp() override {
+        mSeed = static_cast<unsigned int>(time(0));
+        srand(mSeed);
+    }
+};
+
+// UNIT TESTS
+TEST_F(SerializationTest, AudioProductStrategyBinderization) {
+    for (int j = 0; j < 512; j++) {
+        const std::string name{"Test APSBinderization for seed::" + std::to_string(mSeed)};
+        std::vector<AudioAttributes> audioattributesvector;
+        for (auto i = 0; i < 16; i++) {
+            audio_attributes_t attributes;
+            fillAudioAttributes(attributes);
+            AudioAttributes audioattributes{static_cast<volume_group_t>(rand()),
+                                            kStreamtypes[rand() % kStreamtypes.size()], attributes};
+            audioattributesvector.push_back(audioattributes);
+        }
+        product_strategy_t psId = static_cast<product_strategy_t>(rand());
+        AudioProductStrategy aps{name, audioattributesvector, psId};
+
+        Parcel p;
+        EXPECT_EQ(NO_ERROR, aps.writeToParcel(&p)) << name;
+
+        AudioProductStrategy apsCopy;
+        p.setDataPosition(0);
+        EXPECT_EQ(NO_ERROR, apsCopy.readFromParcel(&p)) << name;
+        EXPECT_EQ(apsCopy.getName(), name) << name;
+        EXPECT_EQ(apsCopy.getId(), psId) << name;
+        auto avec = apsCopy.getAudioAttributes();
+        EXPECT_EQ(avec.size(), audioattributesvector.size()) << name;
+        for (int i = 0; i < audioattributesvector.size(); i++) {
+            EXPECT_EQ(avec[i].getGroupId(), audioattributesvector[i].getGroupId()) << name;
+            EXPECT_EQ(avec[i].getStreamType(), audioattributesvector[i].getStreamType()) << name;
+            EXPECT_TRUE(avec[i].getAttributes() == audioattributesvector[i].getAttributes())
+                    << name;
+        }
+    }
+}
+
+TEST_F(SerializationTest, AudioVolumeGroupBinderization) {
+    for (int j = 0; j < 512; j++) {
+        const std::string name{"Test AVGBinderization for seed::" + std::to_string(mSeed)};
+        volume_group_t groupId = static_cast<volume_group_t>(rand());
+        std::vector<audio_attributes_t> attributesvector;
+        for (auto i = 0; i < 16; i++) {
+            audio_attributes_t attributes;
+            fillAudioAttributes(attributes);
+            attributesvector.push_back(attributes);
+        }
+        std::vector<audio_stream_type_t> streamsvector;
+        for (auto i = 0; i < 8; i++) {
+            streamsvector.push_back(kStreamtypes[rand() % kStreamtypes.size()]);
+        }
+        AudioVolumeGroup avg{name, groupId, attributesvector, streamsvector};
+
+        Parcel p;
+        EXPECT_EQ(NO_ERROR, avg.writeToParcel(&p));
+
+        AudioVolumeGroup avgCopy;
+        p.setDataPosition(0);
+        EXPECT_EQ(NO_ERROR, avgCopy.readFromParcel(&p)) << name;
+        EXPECT_EQ(avgCopy.getName(), name) << name;
+        EXPECT_EQ(avgCopy.getId(), groupId) << name;
+        auto avec = avgCopy.getAudioAttributes();
+        EXPECT_EQ(avec.size(), attributesvector.size()) << name;
+        for (int i = 0; i < avec.size(); i++) {
+            EXPECT_TRUE(avec[i] == attributesvector[i]) << name;
+        }
+        StreamTypeVector svec = avgCopy.getStreamTypes();
+        EXPECT_EQ(svec.size(), streamsvector.size()) << name;
+        for (int i = 0; i < svec.size(); i++) {
+            EXPECT_EQ(svec[i], streamsvector[i]) << name;
+        }
+    }
+}
+
+TEST_F(SerializationTest, AudioMixBinderization) {
+    for (int j = 0; j < 512; j++) {
+        const std::string msg{"Test AMBinderization for seed::" + std::to_string(mSeed)};
+        std::vector<AudioMixMatchCriterion> criteria;
+        criteria.reserve(16);
+        for (int i = 0; i < 16; i++) {
+            AudioMixMatchCriterion ammc{kUsages[rand() % kUsages.size()],
+                                        kInputSources[rand() % kInputSources.size()],
+                                        kMixMatchRules[rand() % kMixMatchRules.size()]};
+            criteria.push_back(ammc);
+        }
+        audio_config_t config{};
+        config.sample_rate = 48000;
+        config.channel_mask = AUDIO_CHANNEL_IN_MONO;
+        config.format = AUDIO_FORMAT_PCM_16_BIT;
+        config.offload_info = AUDIO_INFO_INITIALIZER;
+        config.frame_count = 4800;
+        AudioMix am{criteria,
+                    static_cast<uint32_t>(rand()),
+                    config,
+                    static_cast<uint32_t>(rand()),
+                    String8(msg.c_str()),
+                    static_cast<uint32_t>(rand())};
+
+        Parcel p;
+        EXPECT_EQ(NO_ERROR, am.writeToParcel(&p)) << msg;
+
+        AudioMix amCopy;
+        p.setDataPosition(0);
+        EXPECT_EQ(NO_ERROR, amCopy.readFromParcel(&p)) << msg;
+        EXPECT_EQ(amCopy.mMixType, am.mMixType) << msg;
+        EXPECT_EQ(amCopy.mFormat.sample_rate, am.mFormat.sample_rate) << msg;
+        EXPECT_EQ(amCopy.mFormat.channel_mask, am.mFormat.channel_mask) << msg;
+        EXPECT_EQ(amCopy.mFormat.format, am.mFormat.format) << msg;
+        EXPECT_EQ(amCopy.mRouteFlags, am.mRouteFlags) << msg;
+        EXPECT_EQ(amCopy.mDeviceAddress, am.mDeviceAddress) << msg;
+        EXPECT_EQ(amCopy.mCbFlags, am.mCbFlags) << msg;
+        EXPECT_EQ(amCopy.mCriteria.size(), am.mCriteria.size()) << msg;
+        for (auto i = 0; i < amCopy.mCriteria.size(); i++) {
+            EXPECT_EQ(amCopy.mCriteria[i].mRule, am.mCriteria[i].mRule) << msg;
+            EXPECT_EQ(amCopy.mCriteria[i].mValue.mUserId, am.mCriteria[i].mValue.mUserId) << msg;
+        }
+    }
+}
+
+using MMCTestParams = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
+
+class MMCParameterizedTest : public FillAudioAttributes,
+                             public ::testing::TestWithParam<MMCTestParams> {
+  public:
+    MMCParameterizedTest()
+        : mAudioUsage(std::get<0>(GetParam())),
+          mAudioSource(std::get<1>(GetParam())),
+          mAudioMixMatchRules(std::get<2>(GetParam())){};
+
+    const audio_usage_t mAudioUsage;
+    const audio_source_t mAudioSource;
+    const uint32_t mAudioMixMatchRules;
+
+    void SetUp() override {
+        mSeed = static_cast<unsigned int>(time(0));
+        srand(mSeed);
+    }
+};
+
+TEST_P(MMCParameterizedTest, AudioMixMatchCriterionBinderization) {
+    const std::string msg{"Test AMMCBinderization for seed::" + std::to_string(mSeed)};
+    AudioMixMatchCriterion ammc{mAudioUsage, mAudioSource, mAudioMixMatchRules};
+
+    Parcel p;
+    EXPECT_EQ(NO_ERROR, ammc.writeToParcel(&p)) << msg;
+
+    AudioMixMatchCriterion ammcCopy;
+    p.setDataPosition(0);
+    EXPECT_EQ(NO_ERROR, ammcCopy.readFromParcel(&p)) << msg;
+    EXPECT_EQ(ammcCopy.mRule, ammc.mRule) << msg;
+    EXPECT_EQ(ammcCopy.mValue.mUserId, ammc.mValue.mUserId) << msg;
+}
+
+// audioUsage, audioSource, audioMixMatchRules
+INSTANTIATE_TEST_SUITE_P(SerializationParameterizedTests, MMCParameterizedTest,
+                         ::testing::Combine(testing::ValuesIn(kUsages),
+                                            testing::ValuesIn(kInputSources),
+                                            testing::ValuesIn(kMixMatchRules)));
+
+using AudioAttributesTestParams = std::tuple<audio_stream_type_t>;
+
+class AudioAttributesParameterizedTest
+    : public FillAudioAttributes,
+      public ::testing::TestWithParam<AudioAttributesTestParams> {
+  public:
+    AudioAttributesParameterizedTest() : mAudioStream(std::get<0>(GetParam())){};
+
+    const audio_stream_type_t mAudioStream;
+
+    void SetUp() override {
+        mSeed = static_cast<unsigned int>(time(0));
+        srand(mSeed);
+    }
+};
+
+TEST_P(AudioAttributesParameterizedTest, AudioAttributesBinderization) {
+    const std::string msg{"Test AABinderization for seed::" + std::to_string(mSeed)};
+    volume_group_t groupId = static_cast<volume_group_t>(rand());
+    audio_stream_type_t stream = mAudioStream;
+    audio_attributes_t attributes;
+    fillAudioAttributes(attributes);
+    AudioAttributes audioattributes{groupId, stream, attributes};
+
+    Parcel p;
+    EXPECT_EQ(NO_ERROR, audioattributes.writeToParcel(&p)) << msg;
+
+    AudioAttributes audioattributesCopy;
+    p.setDataPosition(0);
+    EXPECT_EQ(NO_ERROR, audioattributesCopy.readFromParcel(&p)) << msg;
+    EXPECT_EQ(audioattributesCopy.getGroupId(), audioattributes.getGroupId()) << msg;
+    EXPECT_EQ(audioattributesCopy.getStreamType(), audioattributes.getStreamType()) << msg;
+    EXPECT_TRUE(audioattributesCopy.getAttributes() == attributes) << msg;
+}
+
+// audioStream
+INSTANTIATE_TEST_SUITE_P(SerializationParameterizedTests, AudioAttributesParameterizedTest,
+                         ::testing::Combine(testing::ValuesIn(kStreamtypes)));
diff --git a/media/libaudioclient/tests/audioeffect_analyser.cpp b/media/libaudioclient/tests/audioeffect_analyser.cpp
new file mode 100644
index 0000000..94accae
--- /dev/null
+++ b/media/libaudioclient/tests/audioeffect_analyser.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "AudioEffectAnalyser"
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_equalizer.h>
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "audio_test_utils.h"
+#include "pffft.hpp"
+
+#define CHECK_OK(expr, msg) \
+    mStatus = (expr);       \
+    if (OK != mStatus) {    \
+        mMsg = (msg);       \
+        return;             \
+    }
+
+using namespace android;
+
+constexpr float kDefAmplitude = 0.60f;
+
+constexpr float kPlayBackDurationSec = 1.5;
+constexpr float kCaptureDurationSec = 1.0;
+constexpr float kPrimeDurationInSec = 0.5;
+
+// chosen to safely sample largest center freq of eq bands
+constexpr uint32_t kSamplingFrequency = 48000;
+
+// allows no fmt conversion before fft
+constexpr audio_format_t kFormat = AUDIO_FORMAT_PCM_FLOAT;
+
+// playback and capture are done with channel mask configured to mono.
+// effect analysis should not depend on mask, mono makes it easier.
+
+constexpr int kNPointFFT = 16384;
+constexpr float kBinWidth = (float)kSamplingFrequency / kNPointFFT;
+
+const char* gPackageName = "AudioEffectAnalyser";
+
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kCaptureDurationSec,
+              "capture at least, prime, pad, nPointFft size of samples");
+static_assert(kPrimeDurationInSec + 2 * kNPointFFT / kSamplingFrequency < kPlayBackDurationSec,
+              "playback needs to be active during capture");
+
+struct CaptureEnv {
+    // input args
+    uint32_t mSampleRate{kSamplingFrequency};
+    audio_format_t mFormat{kFormat};
+    audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_IN_MONO};
+    float mCaptureDuration{kCaptureDurationSec};
+    // output val
+    status_t mStatus{OK};
+    std::string mMsg;
+    std::string mDumpFileName;
+
+    ~CaptureEnv();
+    void capture();
+};
+
+CaptureEnv::~CaptureEnv() {
+    if (!mDumpFileName.empty()) {
+        std::ifstream f(mDumpFileName);
+        if (f.good()) {
+            f.close();
+            remove(mDumpFileName.c_str());
+        }
+    }
+}
+
+void CaptureEnv::capture() {
+    audio_port_v7 port;
+    CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port),
+             "Could not find port")
+    const auto capture =
+            sp<AudioCapture>::make(AUDIO_SOURCE_REMOTE_SUBMIX, mSampleRate, mFormat, mChannelMask);
+    CHECK_OK(capture->create(), "record creation failed")
+    CHECK_OK(capture->setRecordDuration(mCaptureDuration), "set record duration failed")
+    CHECK_OK(capture->enableRecordDump(), "enable record dump failed")
+    auto cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+    CHECK_OK(capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture),
+             "addAudioDeviceCallback failed")
+    CHECK_OK(capture->start(), "start recording failed")
+    CHECK_OK(capture->audioProcess(), "recording process failed")
+    CHECK_OK(cbCapture->waitForAudioDeviceCb(), "audio device callback notification timed out");
+    if (port.id != capture->getAudioRecordHandle()->getRoutedDeviceId()) {
+        CHECK_OK(BAD_VALUE, "Capture NOT routed on expected port")
+    }
+    CHECK_OK(getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port),
+             "Could not find port")
+    CHECK_OK(capture->stop(), "record stop failed")
+    mDumpFileName = capture->getRecordDumpFileName();
+}
+
+struct PlaybackEnv {
+    // input args
+    uint32_t mSampleRate{kSamplingFrequency};
+    audio_format_t mFormat{kFormat};
+    audio_channel_mask_t mChannelMask{AUDIO_CHANNEL_OUT_MONO};
+    audio_session_t mSessionId{AUDIO_SESSION_NONE};
+    std::string mRes;
+    // output val
+    status_t mStatus{OK};
+    std::string mMsg;
+
+    void play();
+};
+
+void PlaybackEnv::play() {
+    const auto ap =
+            sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, AUDIO_OUTPUT_FLAG_NONE,
+                                    mSessionId, AudioTrack::TRANSFER_OBTAIN);
+    CHECK_OK(ap->loadResource(mRes.c_str()), "Unable to open Resource")
+    const auto cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    CHECK_OK(ap->create(), "track creation failed")
+    ap->getAudioTrackHandle()->setVolume(1.0f);
+    CHECK_OK(ap->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback),
+             "addAudioDeviceCallback failed")
+    CHECK_OK(ap->start(), "audio track start failed")
+    CHECK_OK(cbPlayback->waitForAudioDeviceCb(), "audio device callback notification timed out")
+    CHECK_OK(ap->onProcess(), "playback process failed")
+    ap->stop();
+}
+
+void generateMultiTone(const std::vector<int>& toneFrequencies, float samplingFrequency,
+                       float duration, float amplitude, float* buffer, int numSamples) {
+    int totalFrameCount = (samplingFrequency * duration);
+    int limit = std::min(totalFrameCount, numSamples);
+
+    for (auto i = 0; i < limit; i++) {
+        buffer[i] = 0;
+        for (auto j = 0; j < toneFrequencies.size(); j++) {
+            buffer[i] += sin(2 * M_PI * toneFrequencies[j] * i / samplingFrequency);
+        }
+        buffer[i] *= (amplitude / toneFrequencies.size());
+    }
+}
+
+sp<AudioEffect> createEffect(const effect_uuid_t* type,
+                             audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX) {
+    std::string packageName{gPackageName};
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = packageName;
+    attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+    attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+    attributionSource.token = sp<BBinder>::make();
+    sp<AudioEffect> effect = sp<AudioEffect>::make(attributionSource);
+    effect->set(type, nullptr, 0, nullptr, sessionId, AUDIO_IO_HANDLE_NONE, {}, false, false);
+    return effect;
+}
+
+void computeFilterGainsAtTones(float captureDuration, int nPointFft, std::vector<int>& binOffsets,
+                               float* inputMag, float* gaindB, const char* res,
+                               audio_session_t sessionId) {
+    int totalFrameCount = captureDuration * kSamplingFrequency;
+    auto output = pffft::AlignedVector<float>(totalFrameCount);
+    auto fftOutput = pffft::AlignedVector<float>(nPointFft);
+    PlaybackEnv argsP;
+    argsP.mRes = std::string{res};
+    argsP.mSessionId = sessionId;
+    CaptureEnv argsR;
+    argsR.mCaptureDuration = captureDuration;
+    std::thread playbackThread(&PlaybackEnv::play, &argsP);
+    std::thread captureThread(&CaptureEnv::capture, &argsR);
+    captureThread.join();
+    playbackThread.join();
+    ASSERT_EQ(OK, argsR.mStatus) << argsR.mMsg;
+    ASSERT_EQ(OK, argsP.mStatus) << argsP.mMsg;
+    ASSERT_FALSE(argsR.mDumpFileName.empty()) << "recorded not written to file";
+    std::ifstream fin(argsR.mDumpFileName, std::ios::in | std::ios::binary);
+    fin.read((char*)output.data(), totalFrameCount * sizeof(output[0]));
+    fin.close();
+    PFFFT_Setup* handle = pffft_new_setup(nPointFft, PFFFT_REAL);
+    // ignore first few samples. This is to not analyse until audio track is re-routed to remote
+    // submix source, also for the effect filter response to reach steady-state (priming / pruning
+    // samples).
+    int rerouteOffset = kPrimeDurationInSec * kSamplingFrequency;
+    pffft_transform_ordered(handle, output.data() + rerouteOffset, fftOutput.data(), nullptr,
+                            PFFFT_FORWARD);
+    pffft_destroy_setup(handle);
+    for (auto i = 0; i < binOffsets.size(); i++) {
+        auto k = binOffsets[i];
+        auto outputMag = sqrt((fftOutput[k * 2] * fftOutput[k * 2]) +
+                              (fftOutput[k * 2 + 1] * fftOutput[k * 2 + 1]));
+        gaindB[i] = 20 * log10(outputMag / inputMag[i]);
+    }
+}
+
+std::tuple<int, int> roundToFreqCenteredToFftBin(float binWidth, float freq) {
+    int bin_index = std::round(freq / binWidth);
+    int cfreq = std::round(bin_index * binWidth);
+    return std::make_tuple(bin_index, cfreq);
+}
+
+TEST(AudioEffectTest, CheckEqualizerEffect) {
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffect> equalizer = createEffect(SL_IID_EQUALIZER, sessionId);
+    ASSERT_EQ(OK, equalizer->initCheck());
+    ASSERT_EQ(NO_ERROR, equalizer->setEnabled(true));
+    if ((equalizer->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+        GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+    }
+#define MAX_PARAMS 64
+    uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + MAX_PARAMS];
+    effect_param_t* eqParam = (effect_param_t*)(&buf32);
+
+    // get num of presets
+    eqParam->psize = sizeof(uint32_t);
+    eqParam->vsize = sizeof(uint16_t);
+    *(int32_t*)eqParam->data = EQ_PARAM_GET_NUM_OF_PRESETS;
+    EXPECT_EQ(0, equalizer->getParameter(eqParam));
+    EXPECT_EQ(0, eqParam->status);
+    int numPresets = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+    // get num of bands
+    eqParam->psize = sizeof(uint32_t);
+    eqParam->vsize = sizeof(uint16_t);
+    *(int32_t*)eqParam->data = EQ_PARAM_NUM_BANDS;
+    EXPECT_EQ(0, equalizer->getParameter(eqParam));
+    EXPECT_EQ(0, eqParam->status);
+    int numBands = *((uint16_t*)((int32_t*)eqParam->data + 1));
+
+    const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+    // get band center frequencies
+    std::vector<int> centerFrequencies;
+    std::vector<int> binOffsets;
+    for (auto i = 0; i < numBands; i++) {
+        eqParam->psize = sizeof(uint32_t) * 2;
+        eqParam->vsize = sizeof(uint32_t);
+        *(int32_t*)eqParam->data = EQ_PARAM_CENTER_FREQ;
+        *((uint16_t*)((int32_t*)eqParam->data + 1)) = i;
+        EXPECT_EQ(0, equalizer->getParameter(eqParam));
+        EXPECT_EQ(0, eqParam->status);
+        float cfreq = *((int32_t*)eqParam->data + 2) / 1000;  // milli hz
+        // pick frequency close to bin center frequency
+        auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, cfreq);
+        centerFrequencies.push_back(bin_freq);
+        binOffsets.push_back(bin_index);
+    }
+
+    // input for effect module
+    auto input = pffft::AlignedVector<float>(totalFrameCount);
+    generateMultiTone(centerFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+                      input.data(), totalFrameCount);
+    auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+    PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+    pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+    pffft_destroy_setup(handle);
+    float inputMag[numBands];
+    for (auto i = 0; i < numBands; i++) {
+        auto k = binOffsets[i];
+        inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+                           (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+    }
+    TemporaryFile tf("/data/local/tmp");
+    close(tf.release());
+    std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+    fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+    fout.close();
+
+    float expGaindB[numBands], actGaindB[numBands];
+
+    std::string msg = "";
+    int numPresetsOk = 0;
+    for (auto preset = 0; preset < numPresets; preset++) {
+        // set preset
+        eqParam->psize = sizeof(uint32_t);
+        eqParam->vsize = sizeof(uint32_t);
+        *(int32_t*)eqParam->data = EQ_PARAM_CUR_PRESET;
+        *((uint16_t*)((int32_t*)eqParam->data + 1)) = preset;
+        EXPECT_EQ(0, equalizer->setParameter(eqParam));
+        EXPECT_EQ(0, eqParam->status);
+        // get preset gains
+        eqParam->psize = sizeof(uint32_t);
+        eqParam->vsize = (numBands + 1) * sizeof(uint32_t);
+        *(int32_t*)eqParam->data = EQ_PARAM_PROPERTIES;
+        EXPECT_EQ(0, equalizer->getParameter(eqParam));
+        EXPECT_EQ(0, eqParam->status);
+        t_equalizer_settings* settings =
+                reinterpret_cast<t_equalizer_settings*>((int32_t*)eqParam->data + 1);
+        EXPECT_EQ(preset, settings->curPreset);
+        EXPECT_EQ(numBands, settings->numBands);
+        for (auto i = 0; i < numBands; i++) {
+            expGaindB[i] = ((int16_t)settings->bandLevels[i]) / 100.0f;  // gain in milli bels
+        }
+        memset(actGaindB, 0, sizeof(actGaindB));
+        ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+                                                          binOffsets, inputMag, actGaindB, tf.path,
+                                                          sessionId));
+        bool isOk = true;
+        for (auto i = 0; i < numBands - 1; i++) {
+            auto diffA = expGaindB[i] - expGaindB[i + 1];
+            auto diffB = actGaindB[i] - actGaindB[i + 1];
+            if (diffA == 0 && fabs(diffA - diffB) > 1.0f) {
+                msg += (android::base::StringPrintf(
+                        "For eq preset : %d, between bands %d and %d, expected relative gain is : "
+                        "%f, got relative gain is : %f, error : %f \n",
+                        preset, i, i + 1, diffA, diffB, diffA - diffB));
+                isOk = false;
+            } else if (diffA * diffB < 0) {
+                msg += (android::base::StringPrintf(
+                        "For eq preset : %d, between bands %d and %d, expected relative gain and "
+                        "seen relative gain are of opposite signs \n. Expected relative gain is : "
+                        "%f, seen relative gain is : %f \n",
+                        preset, i, i + 1, diffA, diffB));
+                isOk = false;
+            }
+        }
+        if (isOk) numPresetsOk++;
+    }
+    EXPECT_EQ(numPresetsOk, numPresets) << msg;
+}
+
+TEST(AudioEffectTest, CheckBassBoostEffect) {
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffect> bassboost = createEffect(SL_IID_BASSBOOST, sessionId);
+    ASSERT_EQ(OK, bassboost->initCheck());
+    ASSERT_EQ(NO_ERROR, bassboost->setEnabled(true));
+    if ((bassboost->descriptor().flags & EFFECT_FLAG_HW_ACC_MASK) != 0) {
+        GTEST_SKIP() << "effect processed output inaccessible, skipping test";
+    }
+    int32_t buf32[sizeof(effect_param_t) / sizeof(int32_t) + MAX_PARAMS];
+    effect_param_t* bbParam = (effect_param_t*)(&buf32);
+
+    bbParam->psize = sizeof(int32_t);
+    bbParam->vsize = sizeof(int32_t);
+    *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH_SUPPORTED;
+    EXPECT_EQ(0, bassboost->getParameter(bbParam));
+    EXPECT_EQ(0, bbParam->status);
+    bool strengthSupported = *((int32_t*)bbParam->data + 1);
+
+    const int totalFrameCount = kSamplingFrequency * kPlayBackDurationSec;
+
+    // selecting bass frequency, speech tone (for relative gain)
+    std::vector<int> testFrequencies{100, 1200};
+    std::vector<int> binOffsets;
+    for (auto i = 0; i < testFrequencies.size(); i++) {
+        // pick frequency close to bin center frequency
+        auto [bin_index, bin_freq] = roundToFreqCenteredToFftBin(kBinWidth, testFrequencies[i]);
+        testFrequencies[i] = bin_freq;
+        binOffsets.push_back(bin_index);
+    }
+
+    // input for effect module
+    auto input = pffft::AlignedVector<float>(totalFrameCount);
+    generateMultiTone(testFrequencies, kSamplingFrequency, kPlayBackDurationSec, kDefAmplitude,
+                      input.data(), totalFrameCount);
+    auto fftInput = pffft::AlignedVector<float>(kNPointFFT);
+    PFFFT_Setup* handle = pffft_new_setup(kNPointFFT, PFFFT_REAL);
+    pffft_transform_ordered(handle, input.data(), fftInput.data(), nullptr, PFFFT_FORWARD);
+    pffft_destroy_setup(handle);
+    float inputMag[testFrequencies.size()];
+    for (auto i = 0; i < testFrequencies.size(); i++) {
+        auto k = binOffsets[i];
+        inputMag[i] = sqrt((fftInput[k * 2] * fftInput[k * 2]) +
+                           (fftInput[k * 2 + 1] * fftInput[k * 2 + 1]));
+    }
+    TemporaryFile tf("/data/local/tmp");
+    close(tf.release());
+    std::ofstream fout(tf.path, std::ios::out | std::ios::binary);
+    fout.write((char*)input.data(), input.size() * sizeof(input[0]));
+    fout.close();
+
+    float gainWithOutFilter[testFrequencies.size()];
+    memset(gainWithOutFilter, 0, sizeof(gainWithOutFilter));
+    ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT, binOffsets,
+                                                      inputMag, gainWithOutFilter, tf.path,
+                                                      AUDIO_SESSION_OUTPUT_MIX));
+    float diffA = gainWithOutFilter[0] - gainWithOutFilter[1];
+    float prevGain = -100.f;
+    for (auto strength = 150; strength < 1000; strength += strengthSupported ? 150 : 1000) {
+        // configure filter strength
+        if (strengthSupported) {
+            bbParam->psize = sizeof(int32_t);
+            bbParam->vsize = sizeof(int16_t);
+            *(int32_t*)bbParam->data = BASSBOOST_PARAM_STRENGTH;
+            *((int16_t*)((int32_t*)bbParam->data + 1)) = strength;
+            EXPECT_EQ(0, bassboost->setParameter(bbParam));
+            EXPECT_EQ(0, bbParam->status);
+        }
+        float gainWithFilter[testFrequencies.size()];
+        memset(gainWithFilter, 0, sizeof(gainWithFilter));
+        ASSERT_NO_FATAL_FAILURE(computeFilterGainsAtTones(kCaptureDurationSec, kNPointFFT,
+                                                          binOffsets, inputMag, gainWithFilter,
+                                                          tf.path, sessionId));
+        float diffB = gainWithFilter[0] - gainWithFilter[1];
+        EXPECT_GT(diffB, diffA) << "bassboost effect not seen";
+        EXPECT_GE(diffB, prevGain) << "increase in boost strength causing fall in gain";
+        prevGain = diffB;
+    }
+}
diff --git a/media/libaudioclient/tests/audioeffect_tests.cpp b/media/libaudioclient/tests/audioeffect_tests.cpp
new file mode 100644
index 0000000..e6149e4
--- /dev/null
+++ b/media/libaudioclient/tests/audioeffect_tests.cpp
@@ -0,0 +1,559 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioEffectUnitTests"
+
+#include <gtest/gtest.h>
+#include <media/AudioEffect.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_spatializer.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+class AudioEffectCallback : public AudioEffect::IAudioEffectCallback {
+  public:
+    bool receivedFramesProcessed = false;
+
+    void onFramesProcessed(int32_t framesProcessed) override {
+        ALOGE("number of frames processed %d", framesProcessed);
+        receivedFramesProcessed = true;
+    }
+};
+
+static constexpr int kDefaultInputEffectPriority = -1;
+static constexpr int kDefaultOutputEffectPriority = 0;
+
+static const char* gPackageName = "AudioEffectTest";
+
+bool doesDeviceSupportLowLatencyMode(std::vector<struct audio_port_v7>& ports) {
+    for (const auto& port : ports) {
+        if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_MIX) {
+            if ((port.active_config.flags.output & AUDIO_OUTPUT_FLAG_FAST) != 0) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+sp<AudioEffect> createEffect(const effect_uuid_t* type, const effect_uuid_t* uuid = nullptr,
+                             int priority = 0, audio_session_t sessionId = AUDIO_SESSION_OUTPUT_MIX,
+                             const wp<AudioEffectCallback>& callback = nullptr) {
+    std::string packageName{gPackageName};
+    AttributionSourceState attributionSource;
+    attributionSource.packageName = packageName;
+    attributionSource.uid = VALUE_OR_FATAL(legacy2aidl_uid_t_int32_t(getuid()));
+    attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(getpid()));
+    attributionSource.token = sp<BBinder>::make();
+    sp<AudioEffect> effect = new AudioEffect(attributionSource);
+    effect->set(type, uuid, priority, callback, sessionId, AUDIO_IO_HANDLE_NONE, {}, false,
+                (callback != nullptr));
+    return effect;
+}
+
+status_t isEffectExistsOnAudioSession(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();
+}
+
+bool isEffectDefaultOnRecord(const effect_uuid_t* type, const effect_uuid_t* uuid,
+                             const sp<AudioRecord>& audioRecord) {
+    effect_descriptor_t descriptors[AudioEffect::kMaxPreProcessing];
+    uint32_t numEffects = AudioEffect::kMaxPreProcessing;
+    status_t ret = AudioEffect::queryDefaultPreProcessing(audioRecord->getSessionId(), descriptors,
+                                                          &numEffects);
+    if (ret != OK) {
+        return false;
+    }
+    for (int i = 0; i < numEffects; i++) {
+        if ((memcmp(&descriptors[i].type, type, sizeof(effect_uuid_t)) == 0) &&
+            (memcmp(&descriptors[i].uuid, uuid, sizeof(effect_uuid_t)) == 0)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void listEffectsAvailable(std::vector<effect_descriptor_t>& descriptors) {
+    uint32_t numEffects = 0;
+    ASSERT_EQ(NO_ERROR, AudioEffect::queryNumberEffects(&numEffects));
+    for (auto i = 0; i < numEffects; i++) {
+        effect_descriptor_t des;
+        ASSERT_EQ(NO_ERROR, AudioEffect::queryEffect(i, &des));
+        descriptors.push_back(des);
+    }
+}
+
+bool isPreprocessing(effect_descriptor_t& descriptor) {
+    return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC);
+}
+
+bool isInsert(effect_descriptor_t& descriptor) {
+    return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT);
+}
+
+bool isAux(effect_descriptor_t& descriptor) {
+    return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY);
+}
+
+bool isPostproc(effect_descriptor_t& descriptor) {
+    return ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC);
+}
+
+bool isFastCompatible(effect_descriptor_t& descriptor) {
+    return !(((descriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0) &&
+             ((descriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0));
+}
+
+bool isSpatializer(effect_descriptor_t& descriptor) {
+    return (memcmp(&descriptor.type, FX_IID_SPATIALIZER, sizeof(effect_uuid_t)) == 0);
+}
+
+bool isHapticGenerator(effect_descriptor_t& descriptor) {
+    return (memcmp(&descriptor.type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0);
+}
+
+std::tuple<std::string, std::string> typeAndUuidToString(const effect_descriptor_t& desc) {
+    char type[512];
+    AudioEffect::guidToString(&desc.type, type, sizeof(type));
+    char uuid[512];
+    AudioEffect::guidToString(&desc.uuid, uuid, sizeof(uuid));
+    return std::make_tuple(type, uuid);
+}
+
+// UNIT TESTS
+TEST(AudioEffectTest, getEffectDescriptor) {
+    effect_uuid_t randomType = {
+            0x81781c08, 0x93dd, 0x11ec, 0xb909, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+    effect_uuid_t randomUuid = {
+            0x653730e1, 0x1be1, 0x438e, 0xa35a, {0xfc, 0x9b, 0xa1, 0x2a, 0x5e, 0xc9}};
+    effect_uuid_t empty = EFFECT_UUID_INITIALIZER;
+
+    effect_descriptor_t descriptor;
+    EXPECT_EQ(NAME_NOT_FOUND, AudioEffect::getEffectDescriptor(&randomUuid, &randomType,
+                                                               EFFECT_FLAG_TYPE_MASK, &descriptor));
+
+    std::vector<effect_descriptor_t> descriptors;
+    ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+
+    for (auto i = 0; i < descriptors.size(); i++) {
+        EXPECT_EQ(NO_ERROR,
+                  AudioEffect::getEffectDescriptor(&descriptors[i].uuid, &descriptors[i].type,
+                                                   EFFECT_FLAG_TYPE_MASK, &descriptor));
+        EXPECT_EQ(0, memcmp(&descriptor, &descriptors[i], sizeof(effect_uuid_t)));
+    }
+    // negative tests
+    if (descriptors.size() > 0) {
+        EXPECT_EQ(BAD_VALUE,
+                  AudioEffect::getEffectDescriptor(&descriptors[0].uuid, &descriptors[0].type,
+                                                   EFFECT_FLAG_TYPE_MASK, nullptr));
+    }
+    EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(nullptr, nullptr,
+                                                          EFFECT_FLAG_TYPE_PRE_PROC, &descriptor));
+    EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(&empty, &randomType,
+                                                          EFFECT_FLAG_TYPE_MASK, nullptr));
+    EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(nullptr, &randomType,
+                                                          EFFECT_FLAG_TYPE_POST_PROC, &descriptor));
+    EXPECT_EQ(BAD_VALUE, AudioEffect::getEffectDescriptor(&randomUuid, nullptr,
+                                                          EFFECT_FLAG_TYPE_INSERT, &descriptor));
+}
+
+TEST(AudioEffectTest, DISABLED_GetSetParameterForEffect) {
+    sp<AudioEffect> visualizer = createEffect(SL_IID_VISUALIZATION);
+    status_t status = visualizer->initCheck();
+    ASSERT_TRUE(status == NO_ERROR || status == ALREADY_EXISTS) << "Init check error";
+    ASSERT_EQ(NO_ERROR, visualizer->setEnabled(true)) << "visualizer not enabled";
+
+    uint32_t buf32[3][sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+    effect_param_t* vis_none = (effect_param_t*)(buf32[0]);
+    effect_param_t* vis_rms = (effect_param_t*)(buf32[1]);
+    effect_param_t* vis_tmp = (effect_param_t*)(buf32[2]);
+
+    // Visualizer::setMeasurementMode()
+    vis_none->psize = sizeof(uint32_t);
+    vis_none->vsize = sizeof(uint32_t);
+    *(int32_t*)vis_none->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+    *((int32_t*)vis_none->data + 1) = MEASUREMENT_MODE_NONE;
+    EXPECT_EQ(NO_ERROR, visualizer->setParameter(vis_none))
+            << "setMeasurementMode doesn't report success";
+
+    // Visualizer::getMeasurementMode()
+    vis_tmp->psize = sizeof(uint32_t);
+    vis_tmp->vsize = sizeof(uint32_t);
+    *(int32_t*)vis_tmp->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+    *((int32_t*)vis_tmp->data + 1) = 23;
+    EXPECT_EQ(NO_ERROR, visualizer->getParameter(vis_tmp))
+            << "getMeasurementMode doesn't report success";
+    EXPECT_EQ(*((int32_t*)vis_tmp->data + 1), *((int32_t*)vis_none->data + 1))
+            << "target mode does not match set mode";
+
+    // Visualizer::setMeasurementModeDeferred()
+    vis_rms->psize = sizeof(uint32_t);
+    vis_rms->vsize = sizeof(uint32_t);
+    *(int32_t*)vis_rms->data = VISUALIZER_PARAM_MEASUREMENT_MODE;
+    *((int32_t*)vis_rms->data + 1) = MEASUREMENT_MODE_PEAK_RMS;
+    EXPECT_EQ(NO_ERROR, visualizer->setParameterDeferred(vis_rms))
+            << "setMeasurementModeDeferred doesn't report success";
+
+    *((int32_t*)vis_tmp->data + 1) = 23;
+    EXPECT_EQ(NO_ERROR, visualizer->getParameter(vis_tmp))
+            << "getMeasurementMode doesn't report success";
+    EXPECT_EQ(*((int32_t*)vis_tmp->data + 1), *((int32_t*)vis_none->data + 1))
+            << "target mode does not match set mode";
+
+    // setParameterCommit
+    EXPECT_EQ(NO_ERROR, visualizer->setParameterCommit())
+            << "setMeasurementModeCommit does not report success";
+
+    // validate Params
+    *((int32_t*)vis_tmp->data + 1) = 23;
+    EXPECT_EQ(NO_ERROR, visualizer->getParameter(vis_tmp))
+            << "getMeasurementMode doesn't report success";
+    EXPECT_EQ(*((int32_t*)vis_tmp->data + 1), *((int32_t*)vis_rms->data + 1))
+            << "target mode does not match set mode";
+}
+
+TEST(AudioEffectTest, ManageSourceDefaultEffects) {
+    int32_t selectedEffect = -1;
+
+    const uint32_t sampleRate = 44100;
+    const audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
+    const audio_channel_mask_t channelMask = AUDIO_CHANNEL_IN_STEREO;
+    sp<AudioCapture> capture = nullptr;
+
+    std::vector<effect_descriptor_t> descriptors;
+    ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+    for (auto i = 0; i < descriptors.size(); i++) {
+        if (isPreprocessing(descriptors[i])) {
+            capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+            ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+            EXPECT_EQ(NO_ERROR, capture->create());
+            EXPECT_EQ(NO_ERROR, capture->start());
+            if (!isEffectDefaultOnRecord(&descriptors[i].type, &descriptors[i].uuid,
+                                         capture->getAudioRecordHandle())) {
+                selectedEffect = i;
+                break;
+            }
+        }
+    }
+    if (selectedEffect == -1) GTEST_SKIP() << " expected at least one preprocessing effect";
+
+    effect_uuid_t* selectedEffectType = &descriptors[selectedEffect].type;
+    effect_uuid_t* selectedEffectUuid = &descriptors[selectedEffect].uuid;
+    auto [type, uuid] = typeAndUuidToString(descriptors[selectedEffect]);
+    capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+    ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+    EXPECT_EQ(NO_ERROR, capture->create());
+    EXPECT_EQ(NO_ERROR, capture->start());
+    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()))
+            << "Effect should not have been added. " << type;
+    EXPECT_EQ(OK, capture->audioProcess());
+    EXPECT_EQ(OK, capture->stop());
+
+    String16 name{gPackageName};
+    audio_unique_id_t effectId;
+    status_t status = AudioEffect::addSourceDefaultEffect(type.c_str(), name, uuid.c_str(),
+                                                          kDefaultInputEffectPriority,
+                                                          AUDIO_SOURCE_MIC, &effectId);
+    EXPECT_EQ(NO_ERROR, status) << "Adding default effect failed: " << type;
+
+    capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+    ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+    EXPECT_EQ(NO_ERROR, capture->create());
+    EXPECT_EQ(NO_ERROR, capture->start());
+    EXPECT_TRUE(isEffectDefaultOnRecord(selectedEffectType, selectedEffectUuid,
+                                        capture->getAudioRecordHandle()))
+            << "Effect should have been default on record. " << type;
+    EXPECT_EQ(ALREADY_EXISTS,
+              isEffectExistsOnAudioSession(selectedEffectType, selectedEffectUuid,
+                                           kDefaultInputEffectPriority - 1,
+                                           capture->getAudioRecordHandle()->getSessionId()))
+            << "Effect should have been added. " << type;
+    EXPECT_EQ(OK, capture->audioProcess());
+    EXPECT_EQ(OK, capture->stop());
+
+    status = AudioEffect::removeSourceDefaultEffect(effectId);
+    EXPECT_EQ(NO_ERROR, status);
+    capture = new AudioCapture(AUDIO_SOURCE_MIC, sampleRate, format, channelMask);
+    ASSERT_NE(capture, nullptr) << "Unable to create Record Application";
+    EXPECT_EQ(NO_ERROR, capture->create());
+    EXPECT_EQ(NO_ERROR, capture->start());
+    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()))
+            << "Effect should not have been added. " << type;
+    EXPECT_EQ(OK, capture->audioProcess());
+    EXPECT_EQ(OK, capture->stop());
+}
+
+TEST(AudioEffectTest, AuxEffectSanityTest) {
+    int32_t selectedEffect = -1;
+    std::vector<effect_descriptor_t> descriptors;
+    ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+    for (auto i = 0; i < descriptors.size(); i++) {
+        if (isAux(descriptors[i])) {
+            selectedEffect = i;
+            break;
+        }
+    }
+    if (selectedEffect == -1) GTEST_SKIP() << "expected at least one aux effect";
+    effect_uuid_t* selectedEffectType = &descriptors[selectedEffect].type;
+    effect_uuid_t* selectedEffectUuid = &descriptors[selectedEffect].uuid;
+    auto [type, uuid] = typeAndUuidToString(descriptors[selectedEffect]);
+    String16 name{gPackageName};
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffect> audioEffect = createEffect(selectedEffectType, selectedEffectUuid,
+                                               kDefaultInputEffectPriority, sessionId);
+    EXPECT_EQ(NO_INIT, audioEffect->initCheck())
+            << "error, creating auxiliary effect (" << type << ") on session id " << (int)sessionId
+            << " successful ";
+    audio_unique_id_t id;
+    status_t status = AudioEffect::addStreamDefaultEffect(
+            type.c_str(), name, uuid.c_str(), kDefaultOutputEffectPriority, AUDIO_USAGE_MEDIA, &id);
+    if (status == NO_ERROR) {
+        EXPECT_EQ(NO_ERROR, AudioEffect::removeStreamDefaultEffect(id));
+        EXPECT_NE(NO_ERROR, status) << "error, adding auxiliary effect (" << type
+                                    << ") as stream default effect is successful";
+    }
+}
+
+class AudioPlaybackEffectTest : public ::testing::TestWithParam<bool> {
+  public:
+    AudioPlaybackEffectTest() : mSelectFastMode(GetParam()){};
+
+    const bool mSelectFastMode;
+
+    bool mIsFastCompatibleEffect;
+    effect_uuid_t mType;
+    effect_uuid_t mUuid;
+    std::string mTypeStr;
+    std::string mUuidStr;
+
+    void SetUp() override {
+        if (mSelectFastMode) {
+            std::vector<struct audio_port_v7> ports;
+            ASSERT_EQ(OK, listAudioPorts(ports));
+            if (!doesDeviceSupportLowLatencyMode(ports)) {
+                GTEST_SKIP() << "device does not support low latency mode";
+            }
+        }
+
+        int32_t selectedEffect = -1;
+        std::vector<effect_descriptor_t> descriptors;
+        ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+        for (auto i = 0; i < descriptors.size(); i++) {
+            if (isSpatializer(descriptors[i])) continue;
+            if (isHapticGenerator(descriptors[i]) && !AudioSystem::isHapticPlaybackSupported())
+                continue;
+            if (!isInsert(descriptors[i])) continue;
+            selectedEffect = i;
+            mIsFastCompatibleEffect = isFastCompatible(descriptors[i]);
+            // in fast mode, pick fast compatible effect if available
+            if (mSelectFastMode == mIsFastCompatibleEffect) break;
+        }
+        if (selectedEffect == -1) {
+            GTEST_SKIP() << "expected at least one valid effect";
+        }
+
+        mType = descriptors[selectedEffect].type;
+        mUuid = descriptors[selectedEffect].uuid;
+        std::tie(mTypeStr, mUuidStr) = typeAndUuidToString(descriptors[selectedEffect]);
+    }
+};
+
+TEST_P(AudioPlaybackEffectTest, StreamDefaultEffectTest) {
+    SCOPED_TRACE(testing::Message()
+                 << "\n selected effect type is :: " << mTypeStr
+                 << "\n selected effect uuid is :: " << mUuidStr
+                 << "\n audiotrack output flag : " << (mSelectFastMode ? "fast" : "default")
+                 << "\n audio effect is fast compatible : "
+                 << (mIsFastCompatibleEffect ? "yes" : "no"));
+
+    bool compatCheck = !mSelectFastMode || (mSelectFastMode && mIsFastCompatibleEffect);
+
+    // create track
+    audio_attributes_t attributes;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+    auto playback = sp<AudioPlayback>::make(
+            0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+            AudioTrack::TRANSFER_SHARED, &attributes);
+    ASSERT_NE(nullptr, playback);
+    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_EQ(compatCheck ? NO_ERROR : NO_INIT,
+              isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+                                           playback->getAudioTrackHandle()->getSessionId()))
+            << "Effect should not have been added. " << mTypeStr;
+    EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+    playback->stop();
+    playback.clear();
+
+    String16 name{gPackageName};
+    audio_unique_id_t id;
+    status_t status = AudioEffect::addStreamDefaultEffect(mTypeStr.c_str(), name, mUuidStr.c_str(),
+                                                          kDefaultOutputEffectPriority,
+                                                          AUDIO_USAGE_MEDIA, &id);
+    EXPECT_EQ(NO_ERROR, status) << "Adding default effect failed: " << mTypeStr;
+
+    playback = sp<AudioPlayback>::make(
+            0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+            AudioTrack::TRANSFER_SHARED, &attributes);
+    ASSERT_NE(nullptr, playback);
+    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());
+    // 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()))
+            << "Effect should have been added. " << mTypeStr;
+    EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+    if (mSelectFastMode) {
+        EXPECT_EQ(AUDIO_OUTPUT_FLAG_FAST,
+                  playback->getAudioTrackHandle()->getFlags() & AUDIO_OUTPUT_FLAG_FAST);
+    }
+    playback->stop();
+    playback.clear();
+
+    status = AudioEffect::removeStreamDefaultEffect(id);
+    EXPECT_EQ(NO_ERROR, status);
+    playback = sp<AudioPlayback>::make(
+            0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+            AudioTrack::TRANSFER_SHARED, &attributes);
+    ASSERT_NE(nullptr, playback);
+    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_EQ(compatCheck ? NO_ERROR : NO_INIT,
+              isEffectExistsOnAudioSession(&mType, &mUuid, kDefaultOutputEffectPriority - 1,
+                                           playback->getAudioTrackHandle()->getSessionId()))
+            << "Effect should not have been added. " << mTypeStr;
+    EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+    playback->stop();
+    playback.clear();
+}
+
+TEST_P(AudioPlaybackEffectTest, CheckOutputFlagCompatibility) {
+    SCOPED_TRACE(testing::Message()
+                 << "\n selected effect type is :: " << mTypeStr
+                 << "\n selected effect uuid is :: " << mUuidStr
+                 << "\n audiotrack output flag : " << (mSelectFastMode ? "fast" : "default")
+                 << "\n audio effect is fast compatible : "
+                 << (mIsFastCompatibleEffect ? "yes" : "no"));
+
+    audio_attributes_t attributes;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffectCallback> cb = sp<AudioEffectCallback>::make();
+    sp<AudioEffect> audioEffect =
+            createEffect(&mType, &mUuid, kDefaultOutputEffectPriority, sessionId, cb);
+    ASSERT_EQ(OK, audioEffect->initCheck());
+    ASSERT_EQ(NO_ERROR, audioEffect->setEnabled(true));
+    auto playback = sp<AudioPlayback>::make(
+            0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO,
+            mSelectFastMode ? AUDIO_OUTPUT_FLAG_FAST : AUDIO_OUTPUT_FLAG_NONE, sessionId,
+            AudioTrack::TRANSFER_SHARED, &attributes);
+    ASSERT_NE(nullptr, playback);
+    ASSERT_EQ(NO_ERROR, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"));
+    EXPECT_EQ(NO_ERROR, playback->create());
+    EXPECT_EQ(NO_ERROR, playback->start());
+
+    EXPECT_EQ(ALREADY_EXISTS, isEffectExistsOnAudioSession(
+                                      &mType, &mUuid, kDefaultOutputEffectPriority - 1, sessionId))
+            << "Effect should have been added. " << mTypeStr;
+    if (mSelectFastMode) {
+        EXPECT_EQ(mIsFastCompatibleEffect ? AUDIO_OUTPUT_FLAG_FAST : 0,
+                  playback->getAudioTrackHandle()->getFlags() & AUDIO_OUTPUT_FLAG_FAST);
+    }
+    EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+    EXPECT_EQ(NO_ERROR, playback->getAudioTrackHandle()->attachAuxEffect(0));
+    playback->stop();
+    playback.clear();
+    EXPECT_TRUE(cb->receivedFramesProcessed)
+            << "AudioEffect frames processed callback not received";
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectParameterizedTests, AudioPlaybackEffectTest, ::testing::Bool());
+
+TEST(AudioEffectTest, TestHapticEffect) {
+    if (!AudioSystem::isHapticPlaybackSupported())
+        GTEST_SKIP() << "Haptic playback is not supported";
+    int32_t selectedEffect = -1;
+    std::vector<effect_descriptor_t> descriptors;
+    ASSERT_NO_FATAL_FAILURE(listEffectsAvailable(descriptors));
+    for (auto i = 0; i < descriptors.size(); i++) {
+        if (!isHapticGenerator(descriptors[i])) continue;
+        selectedEffect = i;
+        break;
+    }
+    if (selectedEffect == -1) GTEST_SKIP() << "expected at least one valid effect";
+
+    effect_uuid_t* selectedEffectType = &descriptors[selectedEffect].type;
+    effect_uuid_t* selectedEffectUuid = &descriptors[selectedEffect].uuid;
+    auto [type, uuid] = typeAndUuidToString(descriptors[selectedEffect]);
+
+    SCOPED_TRACE(testing::Message() << "\n selected effect type is :: " << type
+                                    << "\n selected effect uuid is :: " << uuid);
+
+    audio_attributes_t attributes;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+    audio_session_t sessionId =
+            (audio_session_t)AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+    sp<AudioEffectCallback> cb = sp<AudioEffectCallback>::make();
+    sp<AudioEffect> audioEffect = createEffect(selectedEffectType, selectedEffectUuid,
+                                               kDefaultOutputEffectPriority, sessionId, cb);
+    ASSERT_EQ(OK, audioEffect->initCheck());
+    ASSERT_EQ(NO_ERROR, audioEffect->setEnabled(true));
+    auto playback = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+                                            AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_NONE,
+                                            sessionId, AudioTrack::TRANSFER_SHARED, &attributes);
+    ASSERT_NE(nullptr, playback);
+    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))
+            << "Effect should have been added. " << type;
+    EXPECT_EQ(NO_ERROR, playback->waitForConsumption());
+    playback->stop();
+    playback.clear();
+    EXPECT_TRUE(cb->receivedFramesProcessed)
+            << "AudioEffect frames processed callback not received";
+}
diff --git a/media/libaudioclient/tests/audiorecord_tests.cpp b/media/libaudioclient/tests/audiorecord_tests.cpp
new file mode 100644
index 0000000..8c63a6d
--- /dev/null
+++ b/media/libaudioclient/tests/audiorecord_tests.cpp
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioRecordTest"
+
+#include <gtest/gtest.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+class AudioRecordTest : public ::testing::Test {
+  public:
+    virtual void SetUp() override {
+        mAC = new AudioCapture(AUDIO_SOURCE_DEFAULT, 44100, AUDIO_FORMAT_PCM_16_BIT,
+                               AUDIO_CHANNEL_IN_FRONT);
+        ASSERT_NE(nullptr, mAC);
+        ASSERT_EQ(OK, mAC->create()) << "record creation failed";
+    }
+
+    virtual void TearDown() override {
+        if (mAC) ASSERT_EQ(OK, mAC->stop());
+    }
+
+    sp<AudioCapture> mAC;
+};
+
+class AudioRecordCreateTest
+    : public ::testing::TestWithParam<
+              std::tuple<uint32_t, audio_format_t, audio_channel_mask_t, audio_input_flags_t,
+                         audio_session_t, audio_source_t>> {
+  public:
+    AudioRecordCreateTest()
+        : mSampleRate(std::get<0>(GetParam())),
+          mFormat(std::get<1>(GetParam())),
+          mChannelMask(std::get<2>(GetParam())),
+          mFlags(std::get<3>(GetParam())),
+          mSessionId(std::get<4>(GetParam())),
+          mInputSource(std::get<5>(GetParam())){};
+
+    const uint32_t mSampleRate;
+    const audio_format_t mFormat;
+    const audio_channel_mask_t mChannelMask;
+    const audio_input_flags_t mFlags;
+    const audio_session_t mSessionId;
+    const audio_source_t mInputSource;
+    const AudioRecord::transfer_type mTransferType = AudioRecord::TRANSFER_OBTAIN;
+
+    sp<AudioCapture> mAC;
+
+    virtual void SetUp() override {
+        mAC = new AudioCapture(mInputSource, mSampleRate, mFormat, mChannelMask, mFlags, mSessionId,
+                               mTransferType);
+        ASSERT_NE(nullptr, mAC);
+        ASSERT_EQ(OK, mAC->create()) << "record creation failed";
+    }
+
+    virtual void TearDown() override {
+        if (mAC) ASSERT_EQ(OK, mAC->stop());
+    }
+};
+
+TEST_F(AudioRecordTest, TestSimpleRecord) {
+    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+}
+
+TEST_F(AudioRecordTest, TestAudioCbNotifier) {
+    EXPECT_EQ(BAD_VALUE, mAC->getAudioRecordHandle()->addAudioDeviceCallback(nullptr));
+    sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
+    sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cbOld));
+    EXPECT_EQ(INVALID_OPERATION, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cbOld));
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->addAudioDeviceCallback(cb));
+    EXPECT_EQ(OK, mAC->start()) << "record creation failed";
+    EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
+    EXPECT_EQ(AUDIO_IO_HANDLE_NONE, cbOld->mAudioIo);
+    EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, cbOld->mDeviceId);
+    EXPECT_NE(AUDIO_IO_HANDLE_NONE, cb->mAudioIo);
+    EXPECT_NE(AUDIO_PORT_HANDLE_NONE, cb->mDeviceId);
+    EXPECT_EQ(BAD_VALUE, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(nullptr));
+    EXPECT_EQ(INVALID_OPERATION, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(cbOld));
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->removeAudioDeviceCallback(cb));
+    mAC->stop();
+}
+
+TEST_F(AudioRecordTest, TestEventRecordTrackPause) {
+    const auto playback = sp<AudioPlayback>::make(
+            8000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO);
+    ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, playback->create()) << "AudioTrack Creation failed";
+    audio_session_t audioTrackSession = playback->getAudioTrackHandle()->getSessionId();
+    EXPECT_EQ(OK, mAC->start(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE, audioTrackSession))
+            << "record creation failed";
+    EXPECT_EQ(OK, playback->start());
+    RawBuffer buffer;
+    status_t status = mAC->obtainBufferCb(buffer);
+    EXPECT_EQ(status, TIMED_OUT) << "Not expecting any callbacks until track sends Sync event";
+    playback->getAudioTrackHandle()->pause();
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+    playback->stop();
+}
+
+TEST_F(AudioRecordTest, TestEventRecordTrackStop) {
+    const auto playback = sp<AudioPlayback>::make(
+            8000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_MONO);
+    ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_1ch_8kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, playback->create()) << "AudioTrack Creation failed";
+    audio_session_t audioTrackSession = playback->getAudioTrackHandle()->getSessionId();
+    EXPECT_EQ(OK, mAC->start(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE, audioTrackSession))
+            << "record creation failed";
+    EXPECT_EQ(OK, playback->start());
+    RawBuffer buffer;
+    status_t status = mAC->obtainBufferCb(buffer);
+    EXPECT_EQ(status, TIMED_OUT) << "Not expecting any callbacks until track sends Sync event";
+    playback->stop();
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+}
+
+TEST_F(AudioRecordTest, TestGetSetMarker) {
+    mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition))
+            << "setMarkerPosition() failed";
+    uint32_t marker;
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker))
+            << "getMarkerPosition() failed";
+    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+    EXPECT_EQ(marker, mAC->mMarkerPosition)
+            << "configured marker and received marker are different";
+    EXPECT_EQ(mAC->mReceivedCbMarkerAtPosition, mAC->mMarkerPosition)
+            << "configured marker and received cb marker are different";
+}
+
+TEST_F(AudioRecordTest, TestGetSetMarkerPeriodical) {
+    mAC->mMarkerPeriod = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPeriod))
+            << "setPositionUpdatePeriod() failed";
+    uint32_t marker;
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker))
+            << "getPositionUpdatePeriod() failed";
+    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+    EXPECT_EQ(marker, mAC->mMarkerPeriod) << "configured marker and received marker are different";
+    EXPECT_EQ(mAC->mReceivedCbMarkerCount, mAC->mNumFramesToRecord / mAC->mMarkerPeriod)
+            << "configured marker and received cb marker are different";
+}
+
+TEST_F(AudioRecordTest, TestGetPosition) {
+    uint32_t position;
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPosition(&position)) << "getPosition() failed";
+    EXPECT_EQ(0, position);
+    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+    EXPECT_EQ(OK, mAC->stop());
+    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPosition(&position)) << "getPosition() failed";
+}
+
+// TODO: Add checkPatchCapture(), verify the information of patch via dumpPort() and dumpPatch()
+TEST_P(AudioRecordCreateTest, TestCreateRecord) {
+    EXPECT_EQ(mFormat, mAC->getAudioRecordHandle()->format());
+    EXPECT_EQ(audio_channel_count_from_in_mask(mChannelMask),
+              mAC->getAudioRecordHandle()->channelCount());
+    if (mAC->mFrameCount != 0)
+        EXPECT_LE(mAC->mFrameCount, mAC->getAudioRecordHandle()->frameCount());
+    EXPECT_EQ(mInputSource, mAC->getAudioRecordHandle()->inputSource());
+    if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAC->getAudioRecordHandle()->getSampleRate());
+    if (mSessionId != AUDIO_SESSION_NONE)
+        EXPECT_EQ(mSessionId, mAC->getAudioRecordHandle()->getSessionId());
+    if (mTransferType != AudioRecord::TRANSFER_CALLBACK) {
+        uint32_t marker;
+        mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
+        EXPECT_EQ(INVALID_OPERATION,
+                  mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition));
+        EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker));
+        EXPECT_EQ(INVALID_OPERATION,
+                  mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPosition));
+        EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker));
+    }
+    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
+    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
+}
+
+// for port primary input
+INSTANTIATE_TEST_SUITE_P(AudioRecordPrimaryInput, AudioRecordCreateTest,
+                         ::testing::Combine(::testing::Values(8000, 11025, 12000, 16000, 22050,
+                                                              24000, 32000, 44100, 48000),
+                                            ::testing::Values(AUDIO_FORMAT_PCM_8_24_BIT),
+                                            ::testing::Values(AUDIO_CHANNEL_IN_MONO,
+                                                              AUDIO_CHANNEL_IN_STEREO,
+                                                              AUDIO_CHANNEL_IN_FRONT_BACK),
+                                            ::testing::Values(AUDIO_INPUT_FLAG_NONE),
+                                            ::testing::Values(AUDIO_SESSION_NONE),
+                                            ::testing::Values(AUDIO_SOURCE_DEFAULT)));
+
+// for port fast input
+INSTANTIATE_TEST_SUITE_P(AudioRecordFastInput, AudioRecordCreateTest,
+                         ::testing::Combine(::testing::Values(8000, 11025, 12000, 16000, 22050,
+                                                              24000, 32000, 44100, 48000),
+                                            ::testing::Values(AUDIO_FORMAT_PCM_8_24_BIT),
+                                            ::testing::Values(AUDIO_CHANNEL_IN_MONO,
+                                                              AUDIO_CHANNEL_IN_STEREO,
+                                                              AUDIO_CHANNEL_IN_FRONT_BACK),
+                                            ::testing::Values(AUDIO_INPUT_FLAG_FAST),
+                                            ::testing::Values(AUDIO_SESSION_NONE),
+                                            ::testing::Values(AUDIO_SOURCE_DEFAULT)));
+
+// misc
+INSTANTIATE_TEST_SUITE_P(AudioRecordMiscInput, AudioRecordCreateTest,
+                         ::testing::Combine(::testing::Values(48000),
+                                            ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
+                                            ::testing::Values(AUDIO_CHANNEL_IN_MONO),
+                                            ::testing::Values(AUDIO_INPUT_FLAG_NONE),
+                                            ::testing::Values(AUDIO_SESSION_NONE),
+                                            ::testing::Values(AUDIO_SOURCE_MIC,
+                                                              AUDIO_SOURCE_CAMCORDER,
+                                                              AUDIO_SOURCE_VOICE_RECOGNITION,
+                                                              AUDIO_SOURCE_VOICE_COMMUNICATION,
+                                                              AUDIO_SOURCE_UNPROCESSED)));
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
new file mode 100644
index 0000000..19d1abc
--- /dev/null
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -0,0 +1,261 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <string.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+// UNIT TEST
+TEST(AudioTrackTest, TestPerformanceMode) {
+    std::vector<struct audio_port_v7> ports;
+    ASSERT_EQ(OK, listAudioPorts(ports));
+    audio_output_flags_t output_flags[] = {AUDIO_OUTPUT_FLAG_FAST, AUDIO_OUTPUT_FLAG_DEEP_BUFFER};
+    audio_flags_mask_t flags[] = {AUDIO_FLAG_LOW_LATENCY, AUDIO_FLAG_DEEP_BUFFER};
+    bool hasFlag = false;
+    for (int i = 0; i < sizeof(flags) / sizeof(flags[0]); i++) {
+        hasFlag = false;
+        for (const auto& port : ports) {
+            if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_MIX) {
+                if ((port.active_config.flags.output & output_flags[i]) != 0) {
+                    hasFlag = true;
+                    break;
+                }
+            }
+        }
+        if (!hasFlag) continue;
+        audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+        attributes.usage = AUDIO_USAGE_MEDIA;
+        attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+        attributes.flags = flags[i];
+        sp<AudioPlayback> ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+                                                       AUDIO_CHANNEL_OUT_STEREO,
+                                                       AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE,
+                                                       AudioTrack::TRANSFER_OBTAIN, &attributes);
+        ASSERT_NE(nullptr, ap);
+        ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+                << "Unable to open Resource";
+        EXPECT_EQ(OK, ap->create()) << "track creation failed";
+        sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
+        EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
+        EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+        EXPECT_EQ(OK, ap->onProcess());
+        EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
+        EXPECT_TRUE(checkPatchPlayback(cb->mAudioIo, cb->mDeviceId));
+        EXPECT_NE(0, ap->getAudioTrackHandle()->getFlags() & output_flags[i]);
+        audio_patch patch;
+        EXPECT_EQ(OK, getPatchForOutputMix(cb->mAudioIo, patch));
+        for (auto j = 0; j < patch.num_sources; j++) {
+            if (patch.sources[j].type == AUDIO_PORT_TYPE_MIX &&
+                patch.sources[j].ext.mix.handle == cb->mAudioIo) {
+                if ((patch.sources[j].flags.output & output_flags[i]) == 0) {
+                    ADD_FAILURE() << "expected output flag " << output_flags[i] << " is absent";
+                    std::cerr << dumpPortConfig(patch.sources[j]);
+                }
+            }
+        }
+        ap->stop();
+    }
+}
+
+TEST(AudioTrackTest, DefaultRoutingTest) {
+    audio_port_v7 port;
+    if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                  AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+        GTEST_SKIP() << "remote submix in device not connected";
+    }
+
+    // create record instance
+    sp<AudioCapture> capture = sp<AudioCapture>::make(
+            AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+    ASSERT_NE(nullptr, capture);
+    EXPECT_EQ(OK, capture->create()) << "record creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture));
+
+    // create playback instance
+    sp<AudioPlayback> playback = sp<AudioPlayback>::make(
+            48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE);
+    ASSERT_NE(nullptr, playback);
+    ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, playback->create()) << "track creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
+
+    // capture should be routed to submix in port
+    EXPECT_EQ(OK, capture->start()) << "start recording failed";
+    EXPECT_EQ(OK, cbCapture->waitForAudioDeviceCb());
+    EXPECT_EQ(port.id, capture->getAudioRecordHandle()->getRoutedDeviceId())
+            << "Capture NOT routed on expected port";
+
+    // capture start should create submix out port
+    status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                          AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // playback should be routed to submix out as long as capture is active
+    EXPECT_EQ(OK, playback->start()) << "audio track start failed";
+    EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+    EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+            << "Playback NOT routed on expected port";
+
+    capture->stop();
+    playback->stop();
+}
+
+class AudioRoutingTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        audio_port_v7 port;
+        if (OK != getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                      AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port)) {
+            GTEST_SKIP() << "remote submix in device not connected";
+        }
+        uint32_t mixType = MIX_TYPE_PLAYERS;
+        uint32_t mixFlag = MIX_ROUTE_FLAG_LOOP_BACK;
+        audio_devices_t deviceType = AUDIO_DEVICE_OUT_REMOTE_SUBMIX;
+        AudioMixMatchCriterion criterion(AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT,
+                                         RULE_MATCH_ATTRIBUTE_USAGE);
+        std::vector<AudioMixMatchCriterion> criteria{criterion};
+        audio_config_t config = AUDIO_CONFIG_INITIALIZER;
+        config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+        config.format = AUDIO_FORMAT_PCM_16_BIT;
+        config.sample_rate = 48000;
+        AudioMix mix(criteria, mixType, config, mixFlag, String8{mAddress.c_str()}, 0);
+        mix.mDeviceType = deviceType;
+        mMixes.push(mix);
+        if (OK == AudioSystem::registerPolicyMixes(mMixes, true)) {
+            mPolicyMixRegistered = true;
+        }
+        ASSERT_TRUE(mPolicyMixRegistered) << "register policy mix failed";
+    }
+
+    void TearDown() override {
+        if (mPolicyMixRegistered) {
+            EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+        }
+    }
+
+    bool mPolicyMixRegistered{false};
+    std::string mAddress{"mix_1"};
+    Vector<AudioMix> mMixes;
+};
+
+TEST_F(AudioRoutingTest, ConcurrentDynamicRoutingTest) {
+    audio_port_v7 port, port_mix;
+    // expect legacy submix in port to be connected
+    status_t status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                          AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // as policy mix is registered, expect submix in port with mAddress to be connected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // create playback instance
+    sp<AudioPlayback> playback = sp<AudioPlayback>::make(
+            48000 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+            AUDIO_OUTPUT_FLAG_NONE, AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
+    ASSERT_NE(nullptr, playback);
+    ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, playback->create()) << "track creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
+
+    // create capture instances on different ports
+    sp<AudioCapture> captureA = sp<AudioCapture>::make(
+            AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
+    ASSERT_NE(nullptr, captureA);
+    EXPECT_EQ(OK, captureA->create()) << "record creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbCaptureA = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, captureA->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureA));
+
+    audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
+    attr.source = AUDIO_SOURCE_REMOTE_SUBMIX;
+    sprintf(attr.tags, "addr=%s", mAddress.c_str());
+    sp<AudioCapture> captureB = sp<AudioCapture>::make(
+            AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
+            AUDIO_INPUT_FLAG_NONE, AUDIO_SESSION_ALLOCATE, AudioRecord::TRANSFER_CALLBACK, &attr);
+    ASSERT_NE(nullptr, captureB);
+    EXPECT_EQ(OK, captureB->create()) << "record creation failed";
+    sp<OnAudioDeviceUpdateNotifier> cbCaptureB = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, captureB->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureB));
+
+    // launch
+    EXPECT_EQ(OK, captureA->start()) << "start recording failed";
+    EXPECT_EQ(OK, cbCaptureA->waitForAudioDeviceCb());
+    EXPECT_EQ(port.id, captureA->getAudioRecordHandle()->getRoutedDeviceId())
+            << "Capture NOT routed on expected port";
+
+    EXPECT_EQ(OK, captureB->start()) << "start recording failed";
+    EXPECT_EQ(OK, cbCaptureB->waitForAudioDeviceCb());
+    EXPECT_EQ(port_mix.id, captureB->getAudioRecordHandle()->getRoutedDeviceId())
+            << "Capture NOT routed on expected port";
+
+    // as record started, expect submix out ports to be connected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "unexpected submix out port found";
+
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_EQ(OK, status) << "Could not find port";
+
+    // check if playback routed to desired port
+    EXPECT_EQ(OK, playback->start());
+    EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb());
+    EXPECT_EQ(port_mix.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+            << "Playback NOT routed on expected port";
+
+    captureB->stop();
+
+    // check if mAddress submix out is disconnected as capture session is stopped
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+    // check if legacy submix out is connected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SINK, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "0", port);
+    EXPECT_EQ(OK, status) << "port not found";
+
+    // unregister policy
+    EXPECT_EQ(OK, AudioSystem::registerPolicyMixes(mMixes, false));
+    mPolicyMixRegistered = false;
+
+    // as policy mix is unregistered, expect submix in port with mAddress to be disconnected
+    status = getPortByAttributes(AUDIO_PORT_ROLE_SOURCE, AUDIO_PORT_TYPE_DEVICE,
+                                 AUDIO_DEVICE_IN_REMOTE_SUBMIX, mAddress, port_mix);
+    EXPECT_NE(OK, status) << "unexpected submix in port found";
+
+    playback->onProcess();
+    // as captureA is active, it should re route to legacy submix
+    EXPECT_EQ(OK, cbPlayback->waitForAudioDeviceCb(port.id));
+    EXPECT_EQ(port.id, playback->getAudioTrackHandle()->getRoutedDeviceId())
+            << "Playback NOT routed on expected port";
+
+    captureA->stop();
+    playback->stop();
+}
diff --git a/media/libaudioclient/tests/audiosystem_tests.cpp b/media/libaudioclient/tests/audiosystem_tests.cpp
new file mode 100644
index 0000000..682f43e
--- /dev/null
+++ b/media/libaudioclient/tests/audiosystem_tests.cpp
@@ -0,0 +1,581 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "AudioSystemTest"
+
+#include <string.h>
+
+#include <gtest/gtest.h>
+#include <media/IAudioFlinger.h>
+#include <utils/Log.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+void anyPatchContainsInputDevice(audio_port_handle_t deviceId, bool& res) {
+    std::vector<struct audio_patch> patches;
+    status_t status = listAudioPatches(patches);
+    ASSERT_EQ(OK, status);
+    res = false;
+    for (const auto& patch : patches) {
+        if (patchContainsInputDevice(deviceId, patch)) {
+            res = true;
+            return;
+        }
+    }
+}
+
+class AudioSystemTest : public ::testing::Test {
+  public:
+    void SetUp() override {
+        mAF = AudioSystem::get_audio_flinger();
+        ASSERT_NE(mAF, nullptr) << "Permission denied";
+    }
+
+    void TearDown() override {
+        if (mPlayback) {
+            mPlayback->stop();
+            mCbPlayback.clear();
+            mPlayback.clear();
+        }
+        if (mCapture) {
+            mCapture->stop();
+            mCbRecord.clear();
+            mCapture.clear();
+        }
+    }
+
+    void createPlaybackSession(void);
+    void createRecordSession(void);
+
+    sp<IAudioFlinger> mAF;
+    sp<AudioPlayback> mPlayback;
+    sp<OnAudioDeviceUpdateNotifier> mCbPlayback;
+    sp<AudioCapture> mCapture;
+    sp<OnAudioDeviceUpdateNotifier> mCbRecord;
+};
+
+void AudioSystemTest::createPlaybackSession(void) {
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+    mPlayback = sp<AudioPlayback>::make(48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+                                        AUDIO_OUTPUT_FLAG_FAST, AUDIO_SESSION_NONE,
+                                        AudioTrack::TRANSFER_SHARED, &attributes);
+    ASSERT_NE(nullptr, mPlayback);
+    ASSERT_EQ(NO_ERROR, mPlayback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"));
+    EXPECT_EQ(NO_ERROR, mPlayback->create());
+    mCbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, mPlayback->getAudioTrackHandle()->addAudioDeviceCallback(mCbPlayback));
+    EXPECT_EQ(NO_ERROR, mPlayback->start());
+    EXPECT_EQ(OK, mPlayback->onProcess());
+    EXPECT_EQ(OK, mCbPlayback->waitForAudioDeviceCb());
+}
+
+void AudioSystemTest::createRecordSession(void) {
+    mCapture = new AudioCapture(AUDIO_SOURCE_DEFAULT, 44100, AUDIO_FORMAT_PCM_8_24_BIT,
+                                AUDIO_CHANNEL_IN_MONO, AUDIO_INPUT_FLAG_FAST);
+    ASSERT_NE(nullptr, mCapture);
+    ASSERT_EQ(OK, mCapture->create()) << "record creation failed";
+    mCbRecord = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, mCapture->getAudioRecordHandle()->addAudioDeviceCallback(mCbRecord));
+    EXPECT_EQ(OK, mCapture->start()) << "record creation failed";
+    EXPECT_EQ(OK, mCbRecord->waitForAudioDeviceCb());
+}
+
+// UNIT TESTS
+TEST_F(AudioSystemTest, CheckServerSideValues) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    EXPECT_GT(mAF->sampleRate(mCbPlayback->mAudioIo), 0);
+    EXPECT_NE(mAF->format(mCbPlayback->mAudioIo), AUDIO_FORMAT_INVALID);
+    EXPECT_GT(mAF->frameCount(mCbPlayback->mAudioIo), 0);
+    size_t frameCountHal, frameCountHalCache;
+    frameCountHal = mAF->frameCountHAL(mCbPlayback->mAudioIo);
+    EXPECT_GT(frameCountHal, 0);
+    EXPECT_EQ(OK, AudioSystem::getFrameCountHAL(mCbPlayback->mAudioIo, &frameCountHalCache));
+    EXPECT_EQ(frameCountHal, frameCountHalCache);
+    EXPECT_GT(mAF->latency(mCbPlayback->mAudioIo), 0);
+    // client side latency is at least server side latency
+    EXPECT_LE(mAF->latency(mCbPlayback->mAudioIo), mPlayback->getAudioTrackHandle()->latency());
+
+    ASSERT_NO_FATAL_FAILURE(createRecordSession());
+    EXPECT_GT(mAF->sampleRate(mCbRecord->mAudioIo), 0);
+    // EXPECT_NE(mAF->format(mCbRecord->mAudioIo), AUDIO_FORMAT_INVALID);
+    EXPECT_GT(mAF->frameCount(mCbRecord->mAudioIo), 0);
+    EXPECT_GT(mAF->frameCountHAL(mCbRecord->mAudioIo), 0);
+    frameCountHal = mAF->frameCountHAL(mCbRecord->mAudioIo);
+    EXPECT_GT(frameCountHal, 0);
+    EXPECT_EQ(OK, AudioSystem::getFrameCountHAL(mCbRecord->mAudioIo, &frameCountHalCache));
+    EXPECT_EQ(frameCountHal, frameCountHalCache);
+    // EXPECT_GT(mAF->latency(mCbRecord->mAudioIo), 0);
+    // client side latency is at least server side latency
+    // EXPECT_LE(mAF->latency(mCbRecord->mAudioIo), mCapture->getAudioRecordHandle()->latency());
+
+    EXPECT_GT(AudioSystem::getPrimaryOutputSamplingRate(), 0);  // first fast mixer sample rate
+    EXPECT_GT(AudioSystem::getPrimaryOutputFrameCount(), 0);    // fast mixer frame count
+}
+
+TEST_F(AudioSystemTest, GetSetMasterVolume) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    float origVol, tstVol;
+    EXPECT_EQ(NO_ERROR, AudioSystem::getMasterVolume(&origVol));
+    float newVol;
+    if (origVol + 0.2f > 1.0f) {
+        newVol = origVol - 0.2f;
+    } else {
+        newVol = origVol + 0.2f;
+    }
+    EXPECT_EQ(NO_ERROR, AudioSystem::setMasterVolume(newVol));
+    EXPECT_EQ(NO_ERROR, AudioSystem::getMasterVolume(&tstVol));
+    EXPECT_EQ(newVol, tstVol);
+    EXPECT_EQ(NO_ERROR, AudioSystem::setMasterVolume(origVol));
+    EXPECT_EQ(NO_ERROR, AudioSystem::getMasterVolume(&tstVol));
+    EXPECT_EQ(origVol, tstVol);
+}
+
+TEST_F(AudioSystemTest, GetSetMasterMute) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    bool origMuteState, tstMuteState;
+    EXPECT_EQ(NO_ERROR, AudioSystem::getMasterMute(&origMuteState));
+    EXPECT_EQ(NO_ERROR, AudioSystem::setMasterMute(!origMuteState));
+    EXPECT_EQ(NO_ERROR, AudioSystem::getMasterMute(&tstMuteState));
+    EXPECT_EQ(!origMuteState, tstMuteState);
+    EXPECT_EQ(NO_ERROR, AudioSystem::setMasterMute(origMuteState));
+    EXPECT_EQ(NO_ERROR, AudioSystem::getMasterMute(&tstMuteState));
+    EXPECT_EQ(origMuteState, tstMuteState);
+}
+
+TEST_F(AudioSystemTest, GetSetMicMute) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    bool origMuteState, tstMuteState;
+    EXPECT_EQ(NO_ERROR, AudioSystem::isMicrophoneMuted(&origMuteState));
+    EXPECT_EQ(NO_ERROR, AudioSystem::muteMicrophone(!origMuteState));
+    EXPECT_EQ(NO_ERROR, AudioSystem::isMicrophoneMuted(&tstMuteState));
+    EXPECT_EQ(!origMuteState, tstMuteState);
+    EXPECT_EQ(NO_ERROR, AudioSystem::muteMicrophone(origMuteState));
+    EXPECT_EQ(NO_ERROR, AudioSystem::isMicrophoneMuted(&tstMuteState));
+    EXPECT_EQ(origMuteState, tstMuteState);
+}
+
+TEST_F(AudioSystemTest, GetSetMasterBalance) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    float origBalance, tstBalance;
+    EXPECT_EQ(OK, AudioSystem::getMasterBalance(&origBalance));
+    float newBalance;
+    if (origBalance + 0.2f > 1.0f) {
+        newBalance = origBalance - 0.2f;
+    } else {
+        newBalance = origBalance + 0.2f;
+    }
+    EXPECT_EQ(OK, AudioSystem::setMasterBalance(newBalance));
+    EXPECT_EQ(OK, AudioSystem::getMasterBalance(&tstBalance));
+    EXPECT_EQ(newBalance, tstBalance);
+    EXPECT_EQ(OK, AudioSystem::setMasterBalance(origBalance));
+    EXPECT_EQ(OK, AudioSystem::getMasterBalance(&tstBalance));
+    EXPECT_EQ(origBalance, tstBalance);
+}
+
+TEST_F(AudioSystemTest, GetStreamVolume) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    float origStreamVol;
+    EXPECT_EQ(NO_ERROR, AudioSystem::getStreamVolume(AUDIO_STREAM_MUSIC, &origStreamVol,
+                                                     mCbPlayback->mAudioIo));
+}
+
+TEST_F(AudioSystemTest, GetStreamMute) {
+    ASSERT_NO_FATAL_FAILURE(createPlaybackSession());
+    bool origMuteState;
+    EXPECT_EQ(NO_ERROR, AudioSystem::getStreamMute(AUDIO_STREAM_MUSIC, &origMuteState));
+}
+
+TEST_F(AudioSystemTest, StartAndStopAudioSource) {
+    std::vector<struct audio_port_v7> ports;
+    audio_port_config sourcePortConfig;
+    audio_attributes_t attributes = AudioSystem::streamTypeToAttributes(AUDIO_STREAM_MUSIC);
+    audio_port_handle_t sourcePortHandle = AUDIO_PORT_HANDLE_NONE;
+
+    status_t status = listAudioPorts(ports);
+    ASSERT_EQ(OK, status);
+    if (ports.empty()) {
+        GTEST_SKIP() << "No ports returned by the audio system";
+    }
+
+    bool sourceFound = false;
+    for (const auto& port : ports) {
+        if (port.role != AUDIO_PORT_ROLE_SOURCE || port.type != AUDIO_PORT_TYPE_DEVICE) continue;
+        if (port.ext.device.type != AUDIO_DEVICE_IN_FM_TUNER) continue;
+        sourceFound = true;
+        sourcePortConfig = port.active_config;
+
+        bool patchFound;
+
+        // start audio source.
+        status_t ret =
+                AudioSystem::startAudioSource(&sourcePortConfig, &attributes, &sourcePortHandle);
+        EXPECT_EQ(OK, ret) << "AudioSystem::startAudioSource for source "
+                           << audio_device_to_string(port.ext.device.type) << " failed";
+        if (ret != OK) continue;
+
+        // verify that patch is established by the source port.
+        ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(port.id, patchFound));
+        EXPECT_EQ(true, patchFound);
+        EXPECT_NE(sourcePortHandle, AUDIO_PORT_HANDLE_NONE);
+
+        if (sourcePortHandle != AUDIO_PORT_HANDLE_NONE) {
+            ret = AudioSystem::stopAudioSource(sourcePortHandle);
+            EXPECT_EQ(OK, ret) << "AudioSystem::stopAudioSource failed for handle "
+                               << sourcePortHandle;
+        }
+
+        // verify that no source port patch exists.
+        ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(port.id, patchFound));
+        EXPECT_EQ(false, patchFound);
+    }
+    if (!sourceFound) {
+        GTEST_SKIP() << "No ports suitable for testing";
+    }
+}
+
+TEST_F(AudioSystemTest, CreateAndReleaseAudioPatch) {
+    status_t status;
+    struct audio_patch audioPatch;
+    std::vector<struct audio_port_v7> ports;
+    audio_patch_handle_t audioPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+
+    bool patchFound = false;
+    audio_port_v7 sourcePort{};
+    audio_port_v7 sinkPort{};
+
+    audioPatch.id = 0;
+    audioPatch.num_sources = 1;
+    audioPatch.num_sinks = 1;
+
+    status = listAudioPorts(ports);
+    ASSERT_EQ(OK, status);
+    if (ports.empty()) {
+        GTEST_SKIP() << "No output devices returned by the audio system";
+    }
+
+    for (const auto& port : ports) {
+        if (port.role == AUDIO_PORT_ROLE_SOURCE && port.type == AUDIO_PORT_TYPE_DEVICE) {
+            sourcePort = port;
+        }
+        if (port.role == AUDIO_PORT_ROLE_SINK && port.type == AUDIO_PORT_TYPE_DEVICE &&
+            port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
+            sinkPort = port;
+        }
+    }
+
+    audioPatch.sources[0] = sourcePort.active_config;
+    audioPatch.sinks[0] = sinkPort.active_config;
+
+    status = AudioSystem::createAudioPatch(&audioPatch, &audioPatchHandle);
+    EXPECT_EQ(OK, status) << "AudioSystem::createAudiopatch failed between source "
+                          << sourcePort.ext.device.address << " and sink "
+                          << sinkPort.ext.device.address;
+
+    // verify that patch is established between source and the sink.
+    ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
+    EXPECT_EQ(true, patchFound);
+
+    EXPECT_NE(AUDIO_PORT_HANDLE_NONE, audioPatchHandle);
+    status = AudioSystem::releaseAudioPatch(audioPatchHandle);
+    EXPECT_EQ(OK, status) << "AudioSystem::releaseAudioPatch failed between source "
+                          << sourcePort.ext.device.address << " and sink "
+                          << sinkPort.ext.device.address;
+
+    // verify that no patch is established between source and the sink after releaseAudioPatch.
+    ASSERT_NO_FATAL_FAILURE(anyPatchContainsInputDevice(sourcePort.id, patchFound));
+    EXPECT_EQ(false, patchFound);
+}
+
+TEST_F(AudioSystemTest, GetAudioPort) {
+    std::vector<struct audio_port_v7> ports;
+    status_t status = listAudioPorts(ports);
+    ASSERT_EQ(OK, status);
+    for (const auto& port : ports) {
+        audio_port_v7 portTest{.id = port.id};
+        EXPECT_EQ(OK, AudioSystem::getAudioPort(&portTest));
+        EXPECT_TRUE(audio_ports_v7_are_equal(&portTest, &port));
+    }
+}
+
+TEST_F(AudioSystemTest, TestPhoneState) {
+    uid_t uid = getuid();
+    EXPECT_EQ(OK, AudioSystem::setPhoneState(AUDIO_MODE_RINGTONE, uid));
+    audio_mode_t state = AudioSystem::getPhoneState();
+    EXPECT_EQ(AUDIO_MODE_RINGTONE, state);
+    EXPECT_EQ(OK, AudioSystem::setPhoneState(AUDIO_MODE_IN_COMMUNICATION, uid));
+    state = AudioSystem::getPhoneState();
+    EXPECT_EQ(AUDIO_MODE_IN_COMMUNICATION, state);
+    EXPECT_EQ(OK, AudioSystem::setPhoneState(AUDIO_MODE_NORMAL, uid));
+    state = AudioSystem::getPhoneState();
+    EXPECT_EQ(AUDIO_MODE_NORMAL, state);
+}
+
+TEST_F(AudioSystemTest, GetDirectProfilesForAttributes) {
+    std::vector<audio_profile> audioProfiles;
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+    EXPECT_EQ(BAD_VALUE, AudioSystem::getDirectProfilesForAttributes(nullptr, nullptr));
+    EXPECT_EQ(BAD_VALUE, AudioSystem::getDirectProfilesForAttributes(nullptr, &audioProfiles));
+    EXPECT_EQ(BAD_VALUE, AudioSystem::getDirectProfilesForAttributes(&attributes, nullptr));
+    EXPECT_EQ(NO_ERROR, AudioSystem::getDirectProfilesForAttributes(&attributes, &audioProfiles));
+}
+
+bool isPublicStrategy(const AudioProductStrategy& strategy) {
+    bool result = true;
+    for (auto& attribute : strategy.getAudioAttributes()) {
+        if (attribute.getAttributes() == AUDIO_ATTRIBUTES_INITIALIZER &&
+            (uint32_t(attribute.getStreamType()) >= AUDIO_STREAM_PUBLIC_CNT)) {
+            result = false;
+            break;
+        }
+    }
+    return result;
+}
+
+TEST_F(AudioSystemTest, DevicesForRoleAndStrategy) {
+    std::vector<struct audio_port_v7> ports;
+    status_t status = listAudioPorts(ports);
+    ASSERT_EQ(OK, status);
+
+    std::vector<struct audio_port_v7> devicePorts;
+    for (const auto& port : ports) {
+        if (port.type == AUDIO_PORT_TYPE_DEVICE && audio_is_output_device(port.ext.device.type)) {
+            devicePorts.push_back(port);
+        }
+    }
+    if (devicePorts.empty()) {
+        GTEST_SKIP() << "No output devices returned by the audio system";
+    }
+
+    AudioProductStrategyVector strategies;
+    EXPECT_EQ(OK, AudioSystem::listAudioProductStrategies(strategies));
+    if (strategies.empty()) {
+        GTEST_SKIP() << "No strategies returned by the audio system";
+    }
+
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+
+    bool hasStrategyForMedia = false;
+    AudioProductStrategy mediaStrategy;
+    for (const auto& strategy : strategies) {
+        if (!isPublicStrategy(strategy)) continue;
+
+        for (const auto& att : strategy.getAudioAttributes()) {
+            if (strategy.attributesMatches(att.getAttributes(), attributes)) {
+                hasStrategyForMedia = true;
+                mediaStrategy = strategy;
+                break;
+            }
+        }
+    }
+
+    if (!hasStrategyForMedia) {
+        GTEST_SKIP() << "No strategies returned for music media";
+    }
+
+    AudioDeviceTypeAddrVector devices;
+    EXPECT_EQ(BAD_VALUE, AudioSystem::getDevicesForRoleAndStrategy(PRODUCT_STRATEGY_NONE,
+                                                                   DEVICE_ROLE_PREFERRED, devices));
+    EXPECT_EQ(BAD_VALUE, AudioSystem::getDevicesForRoleAndStrategy(mediaStrategy.getId(),
+                                                                   DEVICE_ROLE_NONE, devices));
+    status = AudioSystem::getDevicesForRoleAndStrategy(mediaStrategy.getId(), DEVICE_ROLE_PREFERRED,
+                                                       devices);
+    if (status == NAME_NOT_FOUND) {
+        AudioDeviceTypeAddrVector outputDevices;
+        for (const auto& port : devicePorts) {
+            if (port.ext.device.type == AUDIO_DEVICE_OUT_SPEAKER) {
+                const AudioDeviceTypeAddr outputDevice(port.ext.device.type,
+                                                       port.ext.device.address);
+                outputDevices.push_back(outputDevice);
+            }
+        }
+        EXPECT_EQ(OK, AudioSystem::setDevicesRoleForStrategy(mediaStrategy.getId(),
+                                                             DEVICE_ROLE_PREFERRED, outputDevices));
+        EXPECT_EQ(OK, AudioSystem::getDevicesForRoleAndStrategy(mediaStrategy.getId(),
+                                                                DEVICE_ROLE_PREFERRED, devices));
+        EXPECT_EQ(devices, outputDevices);
+        EXPECT_EQ(OK, AudioSystem::removeDevicesRoleForStrategy(mediaStrategy.getId(),
+                                                                DEVICE_ROLE_PREFERRED));
+        EXPECT_EQ(NAME_NOT_FOUND, AudioSystem::getDevicesForRoleAndStrategy(
+                                          mediaStrategy.getId(), DEVICE_ROLE_PREFERRED, devices));
+    }
+}
+
+TEST_F(AudioSystemTest, VolumeIndexForAttributes) {
+    AudioVolumeGroupVector groups;
+    EXPECT_EQ(OK, AudioSystem::listAudioVolumeGroups(groups));
+    for (const auto& group : groups) {
+        if (group.getAudioAttributes().empty()) continue;
+        const audio_attributes_t attr = group.getAudioAttributes()[0];
+        if (attr == AUDIO_ATTRIBUTES_INITIALIZER) continue;
+        audio_stream_type_t streamType = AudioSystem::attributesToStreamType(attr);
+        if (streamType >= AUDIO_STREAM_PUBLIC_CNT) continue;
+
+        volume_group_t vg;
+        EXPECT_EQ(OK, AudioSystem::getVolumeGroupFromAudioAttributes(attr, vg));
+        EXPECT_EQ(group.getId(), vg);
+
+        int index;
+        EXPECT_EQ(OK,
+                  AudioSystem::getVolumeIndexForAttributes(attr, index, AUDIO_DEVICE_OUT_SPEAKER));
+
+        int indexTest;
+        EXPECT_EQ(OK, AudioSystem::getStreamVolumeIndex(streamType, &indexTest,
+                                                        AUDIO_DEVICE_OUT_SPEAKER));
+        EXPECT_EQ(index, indexTest);
+    }
+}
+
+TEST_F(AudioSystemTest, DevicesRoleForCapturePreset) {
+    std::vector<struct audio_port_v7> ports;
+    status_t status = listAudioPorts(ports);
+    ASSERT_EQ(OK, status);
+
+    if (ports.empty()) {
+        GTEST_SKIP() << "No ports returned by the audio system";
+    }
+
+    audio_devices_t inDeviceA = AUDIO_DEVICE_IN_BUILTIN_MIC;
+    audio_devices_t inDeviceB = AUDIO_DEVICE_IN_BUILTIN_MIC;
+    for (const auto& port : ports) {
+        if (port.role != AUDIO_PORT_ROLE_SOURCE || port.type != AUDIO_PORT_TYPE_DEVICE) continue;
+        if (port.ext.device.type == inDeviceA) continue;
+        inDeviceB = port.ext.device.type;
+        break;
+    }
+    const audio_source_t audioSource = AUDIO_SOURCE_MIC;
+    const device_role_t role = DEVICE_ROLE_PREFERRED;
+    const AudioDeviceTypeAddr inputDevice(inDeviceA, "");
+    const AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+    const AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+    const AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+
+    // Test invalid device when setting
+    EXPECT_EQ(BAD_VALUE,
+              AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+    EXPECT_EQ(BAD_VALUE,
+              AudioSystem::addDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+    EXPECT_EQ(BAD_VALUE,
+              AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, outputDevices));
+
+    // Test invalid role
+    AudioDeviceTypeAddrVector devices;
+    EXPECT_EQ(BAD_VALUE, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource,
+                                                                        DEVICE_ROLE_NONE, devices));
+    EXPECT_EQ(BAD_VALUE, AudioSystem::setDevicesRoleForCapturePreset(audioSource, DEVICE_ROLE_NONE,
+                                                                     inputDevices));
+    EXPECT_EQ(BAD_VALUE, AudioSystem::addDevicesRoleForCapturePreset(audioSource, DEVICE_ROLE_NONE,
+                                                                     inputDevices));
+    EXPECT_EQ(BAD_VALUE, AudioSystem::removeDevicesRoleForCapturePreset(
+                                 audioSource, DEVICE_ROLE_NONE, inputDevices));
+    EXPECT_EQ(BAD_VALUE,
+              AudioSystem::clearDevicesRoleForCapturePreset(audioSource, DEVICE_ROLE_NONE));
+
+    // Without setting, call get/remove/clear must fail
+    EXPECT_EQ(NAME_NOT_FOUND,
+              AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+    EXPECT_TRUE(devices.empty());
+    EXPECT_EQ(NAME_NOT_FOUND,
+              AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, devices));
+    EXPECT_EQ(NAME_NOT_FOUND, AudioSystem::clearDevicesRoleForCapturePreset(audioSource, role));
+
+    // Test set/get devices role
+    EXPECT_EQ(NO_ERROR,
+              AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+    ASSERT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+    EXPECT_EQ(devices, inputDevices);
+
+    // Test setting will change the previously set devices
+    const AudioDeviceTypeAddr inputDevice2 = AudioDeviceTypeAddr(inDeviceB, "");
+    AudioDeviceTypeAddrVector inputDevices2 = {inputDevice2};
+    EXPECT_EQ(NO_ERROR,
+              AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, inputDevices2));
+    devices.clear();
+    EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+    EXPECT_EQ(devices, inputDevices2);
+
+    // Test add devices
+    EXPECT_EQ(NO_ERROR,
+              AudioSystem::addDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+    devices.clear();
+    EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+    EXPECT_EQ(2, devices.size());
+    EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice) != devices.end());
+    EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice2) != devices.end());
+
+    // Test remove devices
+    EXPECT_EQ(NO_ERROR,
+              AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+    devices.clear();
+    EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+    EXPECT_EQ(devices, inputDevices2);
+
+    // Test remove devices that are not set as the device role
+    EXPECT_EQ(BAD_VALUE,
+              AudioSystem::removeDevicesRoleForCapturePreset(audioSource, role, inputDevices));
+
+    // Test clear devices
+    EXPECT_EQ(NO_ERROR, AudioSystem::clearDevicesRoleForCapturePreset(audioSource, role));
+    devices.clear();
+    EXPECT_EQ(NAME_NOT_FOUND,
+              AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+
+    AudioDeviceTypeAddrVector inputDevices3 = {inputDevice, inputDevice2};
+    EXPECT_EQ(NO_ERROR,
+              AudioSystem::setDevicesRoleForCapturePreset(audioSource, role, inputDevices3));
+    devices.clear();
+    EXPECT_EQ(NO_ERROR, AudioSystem::getDevicesForRoleAndCapturePreset(audioSource, role, devices));
+    EXPECT_EQ(2, devices.size());
+    EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice) != devices.end());
+    EXPECT_TRUE(std::find(devices.begin(), devices.end(), inputDevice2) != devices.end());
+    EXPECT_EQ(NO_ERROR, AudioSystem::clearDevicesRoleForCapturePreset(audioSource, role));
+}
+
+TEST_F(AudioSystemTest, UidDeviceAffinities) {
+    uid_t uid = getuid();
+
+    // Test invalid device for example audio_is_input_device
+    AudioDeviceTypeAddr inputDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, "");
+    AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+    EXPECT_EQ(BAD_VALUE, AudioSystem::setUidDeviceAffinities(uid, inputDevices));
+
+    // Test valid device for example audio_is_output_device
+    AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+    AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+    EXPECT_EQ(NO_ERROR, AudioSystem::setUidDeviceAffinities(uid, outputDevices));
+    EXPECT_EQ(NO_ERROR, AudioSystem::removeUidDeviceAffinities(uid));
+}
+
+TEST_F(AudioSystemTest, UserIdDeviceAffinities) {
+    int userId = 200;
+
+    // Test invalid device for example audio_is_input_device
+    AudioDeviceTypeAddr inputDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, "");
+    AudioDeviceTypeAddrVector inputDevices = {inputDevice};
+    EXPECT_EQ(BAD_VALUE, AudioSystem::setUserIdDeviceAffinities(userId, inputDevices));
+
+    // Test valid device for ezample audio_is_output_device
+    AudioDeviceTypeAddr outputDevice(AUDIO_DEVICE_OUT_SPEAKER, "");
+    AudioDeviceTypeAddrVector outputDevices = {outputDevice};
+    EXPECT_EQ(NO_ERROR, AudioSystem::setUserIdDeviceAffinities(userId, outputDevices));
+    EXPECT_EQ(NO_ERROR, AudioSystem::removeUserIdDeviceAffinities(userId));
+}
diff --git a/media/libaudioclient/tests/audiotrack_tests.cpp b/media/libaudioclient/tests/audiotrack_tests.cpp
new file mode 100644
index 0000000..8daba0a
--- /dev/null
+++ b/media/libaudioclient/tests/audiotrack_tests.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#include <gtest/gtest.h>
+
+#include "audio_test_utils.h"
+
+using namespace android;
+
+TEST(AudioTrackTest, TestPlayTrack) {
+    const auto ap = sp<AudioPlayback>::make(44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+                                            AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_NONE,
+                                            AUDIO_SESSION_NONE, AudioTrack::TRANSFER_OBTAIN);
+    ASSERT_NE(nullptr, ap);
+    ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, ap->create()) << "track creation failed";
+    EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+    EXPECT_EQ(OK, ap->onProcess());
+    ap->stop();
+}
+
+TEST(AudioTrackTest, TestSeek) {
+    const auto ap = sp<AudioPlayback>::make(
+            44100 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO);
+    ASSERT_NE(nullptr, ap);
+    ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, ap->create()) << "track creation failed";
+    EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+    EXPECT_EQ(OK, ap->onProcess(true));
+    ap->stop();
+}
+
+TEST(AudioTrackTest, OffloadOrDirectPlayback) {
+    audio_offload_info_t info = AUDIO_INFO_INITIALIZER;
+    info.sample_rate = 44100;
+    info.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    info.format = AUDIO_FORMAT_MP3;
+    info.stream_type = AUDIO_STREAM_MUSIC;
+    info.bit_rate = 192;
+    info.duration_us = 120 * 1000000;  // 120 sec
+
+    audio_config_base_t config = {/* .sample_rate = */ info.sample_rate,
+                                  /* .channel_mask = */ info.channel_mask,
+                                  /* .format = */ AUDIO_FORMAT_PCM_16_BIT};
+    audio_attributes_t attributes = AUDIO_ATTRIBUTES_INITIALIZER;
+    attributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
+    attributes.usage = AUDIO_USAGE_MEDIA;
+    attributes.flags = AUDIO_FLAG_NONE;
+
+    if (!AudioTrack::isDirectOutputSupported(config, attributes) &&
+        AUDIO_OFFLOAD_NOT_SUPPORTED == AudioSystem::getOffloadSupport(info)) {
+        GTEST_SKIP() << "offload or direct playback is not supported";
+    }
+    sp<AudioPlayback> ap = nullptr;
+    if (AUDIO_OFFLOAD_NOT_SUPPORTED != AudioSystem::getOffloadSupport(info)) {
+        ap = sp<AudioPlayback>::make(info.sample_rate, info.format, info.channel_mask,
+                                     AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, AUDIO_SESSION_NONE,
+                                     AudioTrack::TRANSFER_OBTAIN, nullptr, &info);
+    } else {
+        ap = sp<AudioPlayback>::make(config.sample_rate, config.format, config.channel_mask,
+                                     AUDIO_OUTPUT_FLAG_DIRECT, AUDIO_SESSION_NONE,
+                                     AudioTrack::TRANSFER_OBTAIN);
+    }
+    ASSERT_NE(nullptr, ap);
+    EXPECT_EQ(OK, ap->create()) << "track creation failed";
+    audio_dual_mono_mode_t mode;
+    if (OK != ap->getAudioTrackHandle()->getDualMonoMode(&mode)) {
+        std::cerr << "no dual mono presentation is available" << std::endl;
+    }
+    if (OK != ap->getAudioTrackHandle()->setDualMonoMode(AUDIO_DUAL_MONO_MODE_LR)) {
+        std::cerr << "no dual mono presentation is available" << std::endl;
+    } else {
+        EXPECT_EQ(OK, ap->getAudioTrackHandle()->getDualMonoMode(&mode));
+        EXPECT_EQ(AUDIO_DUAL_MONO_MODE_LR, mode);
+    }
+    float leveldB;
+    if (OK != ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB)) {
+        std::cerr << "Audio Description mixing is unavailable" << std::endl;
+    }
+    if (OK != ap->getAudioTrackHandle()->setAudioDescriptionMixLevel(3.14f)) {
+        std::cerr << "Audio Description mixing is unavailable" << std::endl;
+    } else {
+        EXPECT_EQ(OK, ap->getAudioTrackHandle()->getAudioDescriptionMixLevel(&leveldB));
+        EXPECT_EQ(3.14f, leveldB);
+    }
+    AudioPlaybackRate audioRate;
+    audioRate = ap->getAudioTrackHandle()->getPlaybackRate();
+    std::cerr << "playback speed :: " << audioRate.mSpeed << std::endl
+              << "playback pitch :: " << audioRate.mPitch << std::endl;
+    audioRate.mSpeed = 2.0f;
+    audioRate.mPitch = 2.0f;
+    audioRate.mStretchMode = AUDIO_TIMESTRETCH_STRETCH_VOICE;
+    audioRate.mFallbackMode = AUDIO_TIMESTRETCH_FALLBACK_MUTE;
+    EXPECT_TRUE(isAudioPlaybackRateValid(audioRate));
+    if (OK != ap->getAudioTrackHandle()->setPlaybackRate(audioRate)) {
+        std::cerr << "unable to set playback rate parameters" << std::endl;
+    } else {
+        AudioPlaybackRate audioRateLocal;
+        audioRateLocal = ap->getAudioTrackHandle()->getPlaybackRate();
+        EXPECT_TRUE(isAudioPlaybackRateEqual(audioRate, audioRateLocal));
+    }
+    ap->stop();
+}
+
+TEST(AudioTrackTest, TestAudioCbNotifier) {
+    const auto ap = sp<AudioPlayback>::make(0 /* sampleRate */, AUDIO_FORMAT_PCM_16_BIT,
+                                            AUDIO_CHANNEL_OUT_STEREO, AUDIO_OUTPUT_FLAG_FAST,
+                                            AUDIO_SESSION_NONE, AudioTrack::TRANSFER_SHARED);
+    ASSERT_NE(nullptr, ap);
+    ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+            << "Unable to open Resource";
+    EXPECT_EQ(OK, ap->create()) << "track creation failed";
+    EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->addAudioDeviceCallback(nullptr));
+    sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
+    sp<OnAudioDeviceUpdateNotifier> cbOld = sp<OnAudioDeviceUpdateNotifier>::make();
+    EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
+    EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->addAudioDeviceCallback(cbOld));
+    EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
+    EXPECT_EQ(OK, ap->start()) << "audio track start failed";
+    EXPECT_EQ(OK, ap->onProcess());
+    EXPECT_EQ(OK, cb->waitForAudioDeviceCb());
+    EXPECT_EQ(AUDIO_IO_HANDLE_NONE, cbOld->mAudioIo);
+    EXPECT_EQ(AUDIO_PORT_HANDLE_NONE, cbOld->mDeviceId);
+    EXPECT_NE(AUDIO_IO_HANDLE_NONE, cb->mAudioIo);
+    EXPECT_NE(AUDIO_PORT_HANDLE_NONE, cb->mDeviceId);
+    EXPECT_EQ(cb->mAudioIo, ap->getAudioTrackHandle()->getOutput());
+    EXPECT_EQ(cb->mDeviceId, ap->getAudioTrackHandle()->getRoutedDeviceId());
+    String8 keys;
+    keys = ap->getAudioTrackHandle()->getParameters(keys);
+    if (!keys.isEmpty()) {
+        std::cerr << "track parameters :: " << keys << std::endl;
+    }
+    EXPECT_TRUE(checkPatchPlayback(cb->mAudioIo, cb->mDeviceId));
+    EXPECT_EQ(BAD_VALUE, ap->getAudioTrackHandle()->removeAudioDeviceCallback(nullptr));
+    EXPECT_EQ(INVALID_OPERATION, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cbOld));
+    EXPECT_EQ(OK, ap->getAudioTrackHandle()->removeAudioDeviceCallback(cb));
+    ap->stop();
+}
+
+class AudioTrackCreateTest
+    : public ::testing::TestWithParam<std::tuple<uint32_t, audio_format_t, audio_channel_mask_t,
+                                                 audio_output_flags_t, audio_session_t>> {
+  public:
+    AudioTrackCreateTest()
+        : mSampleRate(std::get<0>(GetParam())),
+          mFormat(std::get<1>(GetParam())),
+          mChannelMask(std::get<2>(GetParam())),
+          mFlags(std::get<3>(GetParam())),
+          mSessionId(std::get<4>(GetParam())){};
+
+    const uint32_t mSampleRate;
+    const audio_format_t mFormat;
+    const audio_channel_mask_t mChannelMask;
+    const audio_output_flags_t mFlags;
+    const audio_session_t mSessionId;
+
+    sp<AudioPlayback> mAP;
+
+    virtual void SetUp() override {
+        mAP = sp<AudioPlayback>::make(mSampleRate, mFormat, mChannelMask, mFlags,
+                                              mSessionId);
+        ASSERT_NE(nullptr, mAP);
+        ASSERT_EQ(OK, mAP->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
+                << "Unable to open Resource";
+        ASSERT_EQ(OK, mAP->create()) << "track creation failed";
+    }
+
+    virtual void TearDown() override {
+        if (mAP) mAP->stop();
+    }
+};
+
+TEST_P(AudioTrackCreateTest, TestCreateTrack) {
+    EXPECT_EQ(mFormat, mAP->getAudioTrackHandle()->format());
+    EXPECT_EQ(audio_channel_count_from_out_mask(mChannelMask),
+              mAP->getAudioTrackHandle()->channelCount());
+    if (mSampleRate != 0) EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getSampleRate());
+    if (mSessionId != AUDIO_SESSION_NONE)
+        EXPECT_EQ(mSessionId, mAP->getAudioTrackHandle()->getSessionId());
+    EXPECT_EQ(mSampleRate, mAP->getAudioTrackHandle()->getOriginalSampleRate());
+    EXPECT_EQ(OK, mAP->start()) << "audio track start failed";
+    EXPECT_EQ(OK, mAP->onProcess());
+}
+
+// sampleRate, format, channelMask, flags, sessionId
+INSTANTIATE_TEST_SUITE_P(
+        AudioTrackParameterizedTest, AudioTrackCreateTest,
+        ::testing::Combine(::testing::Values(48000), ::testing::Values(AUDIO_FORMAT_PCM_16_BIT),
+                           ::testing::Values(AUDIO_CHANNEL_OUT_STEREO),
+                           ::testing::Values(AUDIO_OUTPUT_FLAG_NONE,
+                                             AUDIO_OUTPUT_FLAG_PRIMARY | AUDIO_OUTPUT_FLAG_FAST,
+                                             AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_FAST,
+                                             AUDIO_OUTPUT_FLAG_DEEP_BUFFER),
+                           ::testing::Values(AUDIO_SESSION_NONE)));
diff --git a/media/libaudioclient/tests/bbb_1ch_8kHz_s16le.raw b/media/libaudioclient/tests/bbb_1ch_8kHz_s16le.raw
new file mode 100644
index 0000000..2d1e4bf
--- /dev/null
+++ b/media/libaudioclient/tests/bbb_1ch_8kHz_s16le.raw
Binary files differ
diff --git a/media/libaudioclient/tests/bbb_2ch_24kHz_s16le.raw b/media/libaudioclient/tests/bbb_2ch_24kHz_s16le.raw
new file mode 100644
index 0000000..c8ac5f7
--- /dev/null
+++ b/media/libaudioclient/tests/bbb_2ch_24kHz_s16le.raw
Binary files differ
diff --git a/media/libaudioclient/tests/test_create_audiorecord.cpp b/media/libaudioclient/tests/test_create_audiorecord.cpp
index 2e0883b..277110b 100644
--- a/media/libaudioclient/tests/test_create_audiorecord.cpp
+++ b/media/libaudioclient/tests/test_create_audiorecord.cpp
@@ -29,14 +29,13 @@
 
 #define NUM_ARGUMENTS 8
 #define VERSION_VALUE "1.0"
-#define PACKAGE_NAME  "AudioRecord test"
+#define PACKAGE_NAME "AudioRecord test"
 
 namespace android {
 
 using android::content::AttributionSourceState;
 
-int testRecord(FILE *inputFile, int outputFileFd)
-{
+int testRecord(FILE* inputFile, int outputFileFd) {
     char line[MAX_INPUT_FILE_LINE_LENGTH];
     uint32_t testCount = 0;
     Vector<String16> args;
@@ -47,11 +46,9 @@
     attributionSource.token = sp<BBinder>::make();
 
     if (inputFile == nullptr) {
-        sp<AudioRecord> record = new AudioRecord(AUDIO_SOURCE_DEFAULT,
-                                              0 /* sampleRate */,
-                                              AUDIO_FORMAT_DEFAULT,
-                                              AUDIO_CHANNEL_IN_MONO,
-                                              attributionSource);
+        sp<AudioRecord> record =
+                new AudioRecord(AUDIO_SOURCE_DEFAULT, 0 /* sampleRate */, AUDIO_FORMAT_DEFAULT,
+                                AUDIO_CHANNEL_IN_MONO, attributionSource);
         if (record == 0 || record->initCheck() != NO_ERROR) {
             write(outputFileFd, "Error creating AudioRecord\n",
                   sizeof("Error creating AudioRecord\n"));
@@ -80,11 +77,10 @@
         char statusStr[MAX_OUTPUT_FILE_LINE_LENGTH];
         bool fast = false;
 
-        if (sscanf(line, " %u %x %x %zu %d %x %u %u",
-                   &sampleRate, &format, &channelMask,
-                   &frameCount, &notificationFrames,
-                   &flags, &sessionId, &inputSource) != NUM_ARGUMENTS) {
-            fprintf(stderr, "Malformed line for test #%u in input file\n", testCount+1);
+        if (sscanf(line, " %u %x %x %zu %d %x %u %u", &sampleRate, &format, &channelMask,
+                   &frameCount, &notificationFrames, &flags, &sessionId,
+                   &inputSource) != NUM_ARGUMENTS) {
+            fprintf(stderr, "Malformed line for test #%u in input file\n", testCount + 1);
             ret = 1;
             continue;
         }
@@ -100,21 +96,10 @@
         sp<AudioRecord> record = new AudioRecord(attributionSource);
         const auto emptyCallback = sp<AudioRecord::IAudioRecordCallback>::make();
 
-        record->set(AUDIO_SOURCE_DEFAULT,
-                   sampleRate,
-                   format,
-                   channelMask,
-                   frameCount,
-                   fast ? emptyCallback : nullptr,
-                   notificationFrames,
-                   false,
-                   sessionId,
-                   fast ? AudioRecord::TRANSFER_CALLBACK : AudioRecord::TRANSFER_DEFAULT,
-                   flags,
-                   getuid(),
-                   getpid(),
-                   &attributes,
-                   AUDIO_PORT_HANDLE_NONE);
+        record->set(AUDIO_SOURCE_DEFAULT, sampleRate, format, channelMask, frameCount,
+                    fast ? emptyCallback : nullptr, notificationFrames, false, sessionId,
+                    fast ? AudioRecord::TRANSFER_CALLBACK : AudioRecord::TRANSFER_DEFAULT, flags,
+                    getuid(), getpid(), &attributes, AUDIO_PORT_HANDLE_NONE);
         status = record->initCheck();
         sprintf(statusStr, "\n#### Test %u status %d\n", testCount, status);
         write(outputFileFd, statusStr, strlen(statusStr));
@@ -126,11 +111,8 @@
     return ret;
 }
 
-}; // namespace android
+};  // namespace android
 
-
-int main(int argc, char **argv)
-{
+int main(int argc, char** argv) {
     return android::main(argc, argv, android::testRecord);
 }
-
diff --git a/media/libaudioclient/tests/test_create_audiotrack.cpp b/media/libaudioclient/tests/test_create_audiotrack.cpp
index e7231d3..4e09e21 100644
--- a/media/libaudioclient/tests/test_create_audiotrack.cpp
+++ b/media/libaudioclient/tests/test_create_audiotrack.cpp
@@ -32,18 +32,15 @@
 
 namespace android {
 
-int testTrack(FILE *inputFile, int outputFileFd)
-{
+int testTrack(FILE* inputFile, int outputFileFd) {
     char line[MAX_INPUT_FILE_LINE_LENGTH];
     uint32_t testCount = 0;
     Vector<String16> args;
     int ret = 0;
 
     if (inputFile == nullptr) {
-        sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_DEFAULT,
-                                              0 /* sampleRate */,
-                                              AUDIO_FORMAT_DEFAULT,
-                                              AUDIO_CHANNEL_OUT_STEREO);
+        sp<AudioTrack> track = new AudioTrack(AUDIO_STREAM_DEFAULT, 0 /* sampleRate */,
+                                              AUDIO_FORMAT_DEFAULT, AUDIO_CHANNEL_OUT_STEREO);
         if (track == 0 || track->initCheck() != NO_ERROR) {
             write(outputFileFd, "Error creating AudioTrack\n",
                   sizeof("Error creating AudioTrack\n"));
@@ -78,11 +75,10 @@
         bool offload = false;
         bool fast = false;
 
-        if (sscanf(line, " %u %x %x %zu %d %u %x %u %u %u",
-                   &sampleRate, &format, &channelMask,
-                   &frameCount, &notificationFrames, &useSharedBuffer,
-                   &flags, &sessionId, &usage, &contentType) != NUM_ARGUMENTS) {
-            fprintf(stderr, "Malformed line for test #%u in input file\n", testCount+1);
+        if (sscanf(line, " %u %x %x %zu %d %u %x %u %u %u", &sampleRate, &format, &channelMask,
+                   &frameCount, &notificationFrames, &useSharedBuffer, &flags, &sessionId, &usage,
+                   &contentType) != NUM_ARGUMENTS) {
+            fprintf(stderr, "Malformed line for test #%u in input file\n", testCount + 1);
             ret = 1;
             continue;
         }
@@ -90,7 +86,7 @@
 
         if (useSharedBuffer != 0) {
             size_t heapSize = audio_channel_count_from_out_mask(channelMask) *
-                    audio_bytes_per_sample(format) * frameCount;
+                              audio_bytes_per_sample(format) * frameCount;
             heap = new MemoryDealer(heapSize, "AudioTrack Heap Base");
             sharedBuffer = heap->allocate(heapSize);
             frameCount = 0;
@@ -111,25 +107,13 @@
         attributes.usage = usage;
         sp<AudioTrack> track = new AudioTrack();
         const auto emptyCallback = sp<AudioTrack::IAudioTrackCallback>::make();
-        track->set(AUDIO_STREAM_DEFAULT,
-                   sampleRate,
-                   format,
-                   channelMask,
-                   frameCount,
-                   flags,
-                   (fast || offload) ? emptyCallback : nullptr,
-                   notificationFrames,
-                   sharedBuffer,
-                   false,
-                   sessionId,
-                   ((fast && sharedBuffer == 0) || offload) ?
-                           AudioTrack::TRANSFER_CALLBACK : AudioTrack::TRANSFER_DEFAULT,
-                   offload ? &offloadInfo : nullptr,
-                   AttributionSourceState(),
-                   &attributes,
-                   false,
-                   1.0f,
-                   AUDIO_PORT_HANDLE_NONE);
+        track->set(AUDIO_STREAM_DEFAULT, sampleRate, format, channelMask, frameCount, flags,
+                   (fast || offload) ? emptyCallback : nullptr, notificationFrames, sharedBuffer,
+                   false, sessionId,
+                   ((fast && sharedBuffer == 0) || offload) ? AudioTrack::TRANSFER_CALLBACK
+                                                            : AudioTrack::TRANSFER_DEFAULT,
+                   offload ? &offloadInfo : nullptr, AttributionSourceState(), &attributes, false,
+                   1.0f, AUDIO_PORT_HANDLE_NONE);
         status = track->initCheck();
         sprintf(statusStr, "\n#### Test %u status %d\n", testCount, status);
         write(outputFileFd, statusStr, strlen(statusStr));
@@ -141,11 +125,8 @@
     return ret;
 }
 
-}; // namespace android
+};  // namespace android
 
-
-int main(int argc, char **argv)
-{
+int main(int argc, char** argv) {
     return android::main(argc, argv, android::testTrack);
 }
-
diff --git a/media/libaudioclient/tests/test_create_utils.cpp b/media/libaudioclient/tests/test_create_utils.cpp
index caf5227..c2c2e8b 100644
--- a/media/libaudioclient/tests/test_create_utils.cpp
+++ b/media/libaudioclient/tests/test_create_utils.cpp
@@ -23,10 +23,10 @@
 
 namespace android {
 
-int readLine(FILE *inputFile, char *line, int size) {
+int readLine(FILE* inputFile, char* line, int size) {
     int ret = 0;
     while (true) {
-        char *str = fgets(line, size, inputFile);
+        char* str = fgets(line, size, inputFile);
         if (str == nullptr) {
             ret = -1;
             break;
@@ -42,8 +42,7 @@
     return ret;
 }
 
-bool checkVersion(FILE *inputFile, const char *version)
-{
+bool checkVersion(FILE* inputFile, const char* version) {
     char line[MAX_INPUT_FILE_LINE_LENGTH];
     char versionKey[MAX_INPUT_FILE_LINE_LENGTH];
     char versionValue[MAX_INPUT_FILE_LINE_LENGTH];
@@ -68,9 +67,8 @@
     return true;
 }
 
-int main(int argc, char **argv, test_func_t testFunc)
-{
-    FILE *inputFile = nullptr;
+int main(int argc, char** argv, test_func_t testFunc) {
+    FILE* inputFile = nullptr;
     int outputFileFd = STDOUT_FILENO;
     mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
     int ret = 0;
@@ -96,7 +94,7 @@
         if (strcmp(*argv, "-o") == 0) {
             argv++;
             if (*argv) {
-                outputFileFd = open(*argv, O_WRONLY|O_CREAT, mode);
+                outputFileFd = open(*argv, O_WRONLY | O_CREAT, mode);
                 if (outputFileFd < 0) {
                     ret = 1;
                 }
@@ -126,5 +124,4 @@
     return ret;
 }
 
-}; // namespace android
-
+};  // namespace android
diff --git a/media/libaudioclient/tests/test_create_utils.h b/media/libaudioclient/tests/test_create_utils.h
index 9a6f9fa..110baf7 100644
--- a/media/libaudioclient/tests/test_create_utils.h
+++ b/media/libaudioclient/tests/test_create_utils.h
@@ -27,13 +27,12 @@
 
 namespace android {
 
-int readLine(FILE *inputFile, char *line, int size);
+int readLine(FILE* inputFile, char* line, int size);
 
-bool checkVersion(FILE *inputFile, const char *version);
+bool checkVersion(FILE* inputFile, const char* version);
 
+typedef int (*test_func_t)(FILE* inputFile, int outputFileFd);
 
-typedef int (*test_func_t)(FILE *inputFile, int outputFileFd);
+int main(int argc, char** argv, test_func_t testFunc);
 
-int main(int argc, char **argv, test_func_t testFunc);
-
-}; // namespace android
+};  // namespace android
diff --git a/media/libaudioclient/tests/trackplayerbase_tests.cpp b/media/libaudioclient/tests/trackplayerbase_tests.cpp
new file mode 100644
index 0000000..c9b704d
--- /dev/null
+++ b/media/libaudioclient/tests/trackplayerbase_tests.cpp
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "TrackPlayerBaseTest"
+
+#include <gtest/gtest.h>
+
+#include <media/TrackPlayerBase.h>
+
+using namespace android;
+using namespace android::media;
+
+class TrackPlayer : public TrackPlayerBase, public AudioTrack::IAudioTrackCallback {
+  public:
+    // methods protected in base class
+    using TrackPlayerBase::playerPause;
+    using TrackPlayerBase::playerSetVolume;
+    using TrackPlayerBase::playerStart;
+    using TrackPlayerBase::playerStop;
+};
+
+class TrackPlayerBaseTest
+    : public ::testing::TestWithParam<std::tuple<double, double, uint32_t, uint32_t>> {
+  public:
+    TrackPlayerBaseTest()
+        : mDuration(std::get<0>(GetParam())),
+          mPulseFreq(std::get<1>(GetParam())),
+          mChannelCount(std::get<2>(GetParam())),
+          mSampleRate(std::get<3>(GetParam())){};
+
+    virtual void SetUp() override {
+        mFrameCount = mDuration * mSampleRate;
+        audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(mChannelCount);
+        sp<AudioTrack> track = new AudioTrack(mStreamType, mSampleRate, mFormat, channelMask,
+                                              mFrameCount, mFlags, nullptr /* callback */,
+                                              0 /* notificationFrames */, AUDIO_SESSION_NONE);
+        ASSERT_EQ(track->initCheck(), NO_ERROR);
+
+        mPlayer = new TrackPlayer();
+        mPlayer->init(track.get(), mPlayer, PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA,
+                      AUDIO_SESSION_NONE);
+        sp<AudioTrack> playerTrack = mPlayer->mAudioTrack;
+        ASSERT_EQ(playerTrack->initCheck(), NO_ERROR);
+
+        mBufferSize = mFrameCount * playerTrack->frameSize();
+        mBuffer.resize(mBufferSize, 0);
+
+        // populate buffer
+        ASSERT_NE(mPulseFreq, 0);
+        int32_t nPulseSamples = mSampleRate / mPulseFreq;
+        int32_t pulseSize = nPulseSamples * playerTrack->frameSize();
+
+        int32_t marker = 0;
+        while (marker + pulseSize <= mBufferSize) {
+            memset(mBuffer.data() + marker, 127, pulseSize / 2);
+            marker += pulseSize;
+        }
+    }
+
+    void playBuffer() {
+        bool blocking = true;
+        ssize_t nbytes = mPlayer->mAudioTrack->write(mBuffer.data(), mBufferSize, blocking);
+        EXPECT_EQ(nbytes, mBufferSize) << "Did not write all data in blocking mode";
+    }
+
+    const double mDuration;  // seconds
+    sp<TrackPlayer> mPlayer;
+
+  private:
+    const double mPulseFreq;
+    const uint32_t mChannelCount;
+    const uint32_t mSampleRate;
+
+    const audio_format_t mFormat = AUDIO_FORMAT_PCM_16_BIT;
+    const audio_output_flags_t mFlags = AUDIO_OUTPUT_FLAG_NONE;
+    const audio_stream_type_t mStreamType = AUDIO_STREAM_MUSIC;
+
+    int32_t mBufferSize;
+    int32_t mFrameCount;
+    std::vector<uint8_t> mBuffer;
+};
+
+class PlaybackTestParam : public TrackPlayerBaseTest {};
+
+TEST_P(PlaybackTestParam, PlaybackTest) {
+    // no-op implementation
+    EXPECT_TRUE(mPlayer->setStartDelayMs(0).isOk());
+
+    ASSERT_EQ(mPlayer->playerStart(), NO_ERROR);
+    ASSERT_NO_FATAL_FAILURE(playBuffer());
+    EXPECT_EQ(mPlayer->playerStop(), NO_ERROR);
+}
+
+INSTANTIATE_TEST_SUITE_P(TrackPlayerTest, PlaybackTestParam,
+                         ::testing::Values(std::make_tuple(2.5, 25.0, 2, 48000)));
+
+class ChangeVolumeTestParam : public TrackPlayerBaseTest {};
+
+TEST_P(ChangeVolumeTestParam, ChangeVolumeTest) {
+    float volume = 1.0f;
+    (void)mPlayer->setPlayerVolume(volume / 2, volume);
+
+    ASSERT_TRUE(mPlayer->start().isOk());
+    ASSERT_EQ(mPlayer->playerSetVolume(), NO_ERROR);
+
+    ASSERT_NO_FATAL_FAILURE(playBuffer());
+
+    EXPECT_TRUE(mPlayer->stop().isOk());
+
+    std::vector<float> setVol = {0.95f, 0.05f, 0.5f, 0.25f, -1.0f, 1.0f, 1.0f};
+    std::vector<float> setPan = {0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.5f, -0.5f};
+
+    ASSERT_TRUE(mPlayer->start().isOk());
+
+    for (int32_t i = 0; i < setVol.size(); i++) {
+        EXPECT_TRUE(mPlayer->setVolume(setVol[i]).isOk());
+        EXPECT_TRUE(mPlayer->setPan(setPan[i]).isOk());
+        ASSERT_NO_FATAL_FAILURE(playBuffer());
+    }
+    EXPECT_TRUE(mPlayer->stop().isOk());
+}
+
+INSTANTIATE_TEST_SUITE_P(TrackPlayerTest, ChangeVolumeTestParam,
+                         ::testing::Values(std::make_tuple(1.0, 100.0, 1, 24000)));
+
+class PauseTestParam : public TrackPlayerBaseTest {};
+
+TEST_P(PauseTestParam, PauseTest) {
+    ASSERT_EQ(mPlayer->playerStart(), NO_ERROR);
+    ASSERT_NO_FATAL_FAILURE(playBuffer());
+
+    ASSERT_EQ(mPlayer->playerPause(), NO_ERROR);
+    ASSERT_EQ(mPlayer->playerStart(), NO_ERROR);
+
+    ASSERT_NO_FATAL_FAILURE(playBuffer());
+
+    EXPECT_EQ(mPlayer->playerStop(), NO_ERROR);
+
+    for (int32_t i = 0; i < 5; i++) {
+        ASSERT_TRUE(mPlayer->start().isOk());
+        ASSERT_NO_FATAL_FAILURE(playBuffer());
+        ASSERT_TRUE(mPlayer->pause().isOk());
+    }
+    EXPECT_TRUE(mPlayer->stop().isOk());
+}
+
+INSTANTIATE_TEST_SUITE_P(TrackPlayerTest, PauseTestParam,
+                         ::testing::Values(std::make_tuple(1.0, 75.0, 2, 24000)));
diff --git a/media/libaudiofoundation/Android.bp b/media/libaudiofoundation/Android.bp
index 159f898..c758fcd 100644
--- a/media/libaudiofoundation/Android.bp
+++ b/media/libaudiofoundation/Android.bp
@@ -18,21 +18,22 @@
 
     export_include_dirs: ["include"],
     header_libs: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
         "libaudio_system_headers",
         "libmedia_helper_headers",
     ],
     export_header_lib_headers: [
-        "libaudioclient_aidl_conversion_util",
+        "libaudio_aidl_conversion_common_util_cpp",
         "libaudio_system_headers",
         "libmedia_helper_headers",
     ],
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_export_static",
+    ],
     static_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
     ],
     export_static_lib_headers: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
     ],
     host_supported: true,
@@ -57,8 +58,11 @@
         "DeviceDescriptorBase.cpp",
     ],
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_export_shared",
+    ],
+
     shared_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
         "libaudioutils",
@@ -70,7 +74,6 @@
     ],
 
     export_shared_lib_headers: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
     ],
diff --git a/media/libaudiofoundation/AudioContainers.cpp b/media/libaudiofoundation/AudioContainers.cpp
index 0a8188f..202a400 100644
--- a/media/libaudiofoundation/AudioContainers.cpp
+++ b/media/libaudiofoundation/AudioContainers.cpp
@@ -77,6 +77,13 @@
     return audioDeviceOutLeAudioUnicastSet;
 }
 
+const DeviceTypeSet& getAudioDeviceOutLeAudioBroadcastSet() {
+    static const DeviceTypeSet audioDeviceOutLeAudioUnicastSet = DeviceTypeSet(
+            std::begin(AUDIO_DEVICE_OUT_BLE_BROADCAST_ARRAY),
+            std::end(AUDIO_DEVICE_OUT_BLE_BROADCAST_ARRAY));
+    return audioDeviceOutLeAudioUnicastSet;
+}
+
 std::string deviceTypesToString(const DeviceTypeSet &deviceTypes) {
     if (deviceTypes.empty()) {
         return "Empty device types";
diff --git a/media/libaudiofoundation/AudioPort.cpp b/media/libaudiofoundation/AudioPort.cpp
index 4513323..6e05abc 100644
--- a/media/libaudiofoundation/AudioPort.cpp
+++ b/media/libaudiofoundation/AudioPort.cpp
@@ -222,7 +222,7 @@
            mExtraAudioDescriptors == other->getExtraAudioDescriptors();
 }
 
-status_t AudioPort::writeToParcelable(media::AudioPort* parcelable) const {
+status_t AudioPort::writeToParcelable(media::AudioPortFw* parcelable) const {
     parcelable->hal.name = mName;
     parcelable->sys.type = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_port_type_t_AudioPortType(mType));
@@ -249,7 +249,7 @@
     return OK;
 }
 
-status_t AudioPort::readFromParcelable(const media::AudioPort& parcelable) {
+status_t AudioPort::readFromParcelable(const media::AudioPortFw& parcelable) {
     mName = parcelable.hal.name;
     mType = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioPortType_audio_port_type_t(parcelable.sys.type));
diff --git a/media/libaudiofoundation/DeviceDescriptorBase.cpp b/media/libaudiofoundation/DeviceDescriptorBase.cpp
index 5ffbffc..9ffc75b 100644
--- a/media/libaudiofoundation/DeviceDescriptorBase.cpp
+++ b/media/libaudiofoundation/DeviceDescriptorBase.cpp
@@ -174,7 +174,7 @@
     return false;
 }
 
-status_t DeviceDescriptorBase::writeToParcelable(media::AudioPort* parcelable) const {
+status_t DeviceDescriptorBase::writeToParcelable(media::AudioPortFw* parcelable) const {
     AudioPort::writeToParcelable(parcelable);
     AudioPortConfig::writeToParcelable(&parcelable->sys.activeConfig.hal, useInputChannelMask());
     parcelable->hal.id = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_port_handle_t_int32_t(mId));
@@ -186,17 +186,17 @@
     deviceExt.encodedFormats = VALUE_OR_RETURN_STATUS(
             convertContainer<std::vector<media::audio::common::AudioFormatDescription>>(
                     mEncodedFormats, legacy2aidl_audio_format_t_AudioFormatDescription));
+    deviceExt.encapsulationModes = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_AudioEncapsulationMode_mask(mEncapsulationModes));
+    deviceExt.encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
+            legacy2aidl_AudioEncapsulationMetadataType_mask(mEncapsulationMetadataTypes));
     UNION_SET(parcelable->hal.ext, device, deviceExt);
     media::AudioPortDeviceExtSys deviceSys;
-    deviceSys.encapsulationModes = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioEncapsulationMode_mask(mEncapsulationModes));
-    deviceSys.encapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
-            legacy2aidl_AudioEncapsulationMetadataType_mask(mEncapsulationMetadataTypes));
     UNION_SET(parcelable->sys.ext, device, deviceSys);
     return OK;
 }
 
-status_t DeviceDescriptorBase::readFromParcelable(const media::AudioPort& parcelable) {
+status_t DeviceDescriptorBase::readFromParcelable(const media::AudioPortFw& parcelable) {
     if (parcelable.sys.type != media::AudioPortType::DEVICE) {
         return BAD_VALUE;
     }
@@ -214,12 +214,12 @@
     mEncodedFormats = VALUE_OR_RETURN_STATUS(
             convertContainer<FormatVector>(deviceExt.encodedFormats,
                     aidl2legacy_AudioFormatDescription_audio_format_t));
+    mEncapsulationModes = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioEncapsulationMode_mask(deviceExt.encapsulationModes));
+    mEncapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
+            aidl2legacy_AudioEncapsulationMetadataType_mask(deviceExt.encapsulationMetadataTypes));
     media::AudioPortDeviceExtSys deviceSys = VALUE_OR_RETURN_STATUS(
             UNION_GET(parcelable.sys.ext, device));
-    mEncapsulationModes = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioEncapsulationMode_mask(deviceSys.encapsulationModes));
-    mEncapsulationMetadataTypes = VALUE_OR_RETURN_STATUS(
-            aidl2legacy_AudioEncapsulationMetadataType_mask(deviceSys.encapsulationMetadataTypes));
     return OK;
 }
 
@@ -245,7 +245,7 @@
 }
 
 ConversionResult<sp<DeviceDescriptorBase>>
-aidl2legacy_DeviceDescriptorBase(const media::AudioPort& aidl) {
+aidl2legacy_DeviceDescriptorBase(const media::AudioPortFw& aidl) {
     sp<DeviceDescriptorBase> result = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
     status_t status = result->readFromParcelable(aidl);
     if (status != OK) {
@@ -254,9 +254,9 @@
     return result;
 }
 
-ConversionResult<media::AudioPort>
+ConversionResult<media::AudioPortFw>
 legacy2aidl_DeviceDescriptorBase(const sp<DeviceDescriptorBase>& legacy) {
-    media::AudioPort aidl;
+    media::AudioPortFw aidl;
     status_t status = legacy->writeToParcelable(&aidl);
     if (status != OK) {
         return base::unexpected(status);
diff --git a/media/libaudiofoundation/include/media/AudioContainers.h b/media/libaudiofoundation/include/media/AudioContainers.h
index b6e6c84..3f79ea2 100644
--- a/media/libaudiofoundation/include/media/AudioContainers.h
+++ b/media/libaudiofoundation/include/media/AudioContainers.h
@@ -42,6 +42,7 @@
 const DeviceTypeSet& getAudioDeviceInAllUsbSet();
 const DeviceTypeSet& getAudioDeviceOutAllBleSet();
 const DeviceTypeSet& getAudioDeviceOutLeAudioUnicastSet();
+const DeviceTypeSet& getAudioDeviceOutLeAudioBroadcastSet();
 
 template<typename T>
 static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
@@ -66,6 +67,9 @@
     for (const auto &channel : channelMasks) {
         if (audio_channel_mask_out_to_in(channel) != AUDIO_CHANNEL_INVALID) {
             inMaskSet.insert(audio_channel_mask_out_to_in(channel));
+        } else if (audio_channel_mask_get_representation(channel)
+                    == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+            inMaskSet.insert(channel);
         }
     }
     return inMaskSet;
@@ -76,6 +80,9 @@
     for (const auto &channel : channelMasks) {
         if (audio_channel_mask_in_to_out(channel) != AUDIO_CHANNEL_INVALID) {
             outMaskSet.insert(audio_channel_mask_in_to_out(channel));
+        } else if (audio_channel_mask_get_representation(channel)
+                    == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
+            outMaskSet.insert(channel);
         }
     }
     return outMaskSet;
diff --git a/media/libaudiofoundation/include/media/AudioPort.h b/media/libaudiofoundation/include/media/AudioPort.h
index d6a098f..77e58ed 100644
--- a/media/libaudiofoundation/include/media/AudioPort.h
+++ b/media/libaudiofoundation/include/media/AudioPort.h
@@ -19,8 +19,8 @@
 #include <string>
 #include <type_traits>
 
-#include <android/media/AudioPort.h>
-#include <android/media/AudioPortConfig.h>
+#include <android/media/AudioPortFw.h>
+#include <android/media/AudioPortConfigFw.h>
 #include <android/media/audio/common/ExtraAudioDescriptor.h>
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
@@ -72,7 +72,7 @@
     AudioProfileVector &getAudioProfiles() { return mProfiles; }
 
     void setExtraAudioDescriptors(
-            const std::vector<media::audio::common::ExtraAudioDescriptor> extraAudioDescriptors) {
+            const std::vector<media::audio::common::ExtraAudioDescriptor>& extraAudioDescriptors) {
         mExtraAudioDescriptors = extraAudioDescriptors;
     }
     std::vector<media::audio::common::ExtraAudioDescriptor> &getExtraAudioDescriptors() {
@@ -118,8 +118,8 @@
 
     bool equals(const sp<AudioPort>& other) const;
 
-    status_t writeToParcelable(media::AudioPort* parcelable) const;
-    status_t readFromParcelable(const media::AudioPort& parcelable);
+    status_t writeToParcelable(media::AudioPortFw* parcelable) const;
+    status_t readFromParcelable(const media::AudioPortFw& parcelable);
 
     AudioGains mGains; // gain controllers
     // Maximum number of input or output streams that can be simultaneously
diff --git a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
index 1f0c768..501831d 100644
--- a/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
+++ b/media/libaudiofoundation/include/media/DeviceDescriptorBase.h
@@ -18,7 +18,7 @@
 
 #include <vector>
 
-#include <android/media/AudioPort.h>
+#include <android/media/AudioPortFw.h>
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 #include <media/AudioContainers.h>
@@ -53,7 +53,7 @@
 
     // AudioPortConfig
     virtual sp<AudioPort> getAudioPort() const {
-        return static_cast<AudioPort*>(const_cast<DeviceDescriptorBase*>(this));
+        return sp<AudioPort>::fromExisting(const_cast<DeviceDescriptorBase*>(this));
     }
     virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
             const struct audio_port_config *srcConfig = NULL) const;
@@ -79,8 +79,8 @@
 
     bool equals(const sp<DeviceDescriptorBase>& other) const;
 
-    status_t writeToParcelable(media::AudioPort* parcelable) const;
-    status_t readFromParcelable(const media::AudioPort& parcelable);
+    status_t writeToParcelable(media::AudioPortFw* parcelable) const;
+    status_t readFromParcelable(const media::AudioPortFw& parcelable);
 
 protected:
     AudioDeviceTypeAddr mDeviceTypeAddr;
@@ -116,8 +116,8 @@
 
 // Conversion routines, according to AidlConversion.h conventions.
 ConversionResult<sp<DeviceDescriptorBase>>
-aidl2legacy_DeviceDescriptorBase(const media::AudioPort& aidl);
-ConversionResult<media::AudioPort>
+aidl2legacy_DeviceDescriptorBase(const media::AudioPortFw& aidl);
+ConversionResult<media::AudioPortFw>
 legacy2aidl_DeviceDescriptorBase(const sp<DeviceDescriptorBase>& legacy);
 
 } // namespace android
diff --git a/media/libaudiofoundation/tests/Android.bp b/media/libaudiofoundation/tests/Android.bp
index 3f1fbea..2f4aee0 100644
--- a/media/libaudiofoundation/tests/Android.bp
+++ b/media/libaudiofoundation/tests/Android.bp
@@ -10,6 +10,9 @@
 cc_test {
     name: "audiofoundation_parcelable_test",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
     shared_libs: [
         "libbase",
         "libbinder",
@@ -18,9 +21,9 @@
     ],
 
     static_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "libaudioclient_aidl_conversion",
+        "libaudio_aidl_conversion_common_cpp",
         "libaudiofoundation",
         "libstagefright_foundation",
     ],
diff --git a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
index 50d8dc8..e315858 100644
--- a/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
+++ b/media/libaudiofoundation/tests/audiofoundation_parcelable_test.cpp
@@ -117,7 +117,7 @@
     audioPort->setGains(getAudioGainsForTest());
     audioPort->setAudioProfiles(getAudioProfileVectorForTest());
 
-    media::AudioPort parcelable;
+    media::AudioPortFw parcelable;
     ASSERT_EQ(NO_ERROR, audioPort->writeToParcelable(&parcelable));
     sp<AudioPort> audioPortFromParcel = new AudioPort(
             "", AUDIO_PORT_TYPE_NONE, AUDIO_PORT_ROLE_NONE);
@@ -152,7 +152,7 @@
     ASSERT_EQ(desc->setEncapsulationMetadataTypes(
             AUDIO_ENCAPSULATION_METADATA_TYPE_ALL_POSITION_BITS), NO_ERROR);
 
-    media::AudioPort parcelable;
+    media::AudioPortFw parcelable;
     ASSERT_EQ(NO_ERROR, desc->writeToParcelable(&parcelable));
     sp<DeviceDescriptorBase> descFromParcel = new DeviceDescriptorBase(AUDIO_DEVICE_NONE);
     ASSERT_EQ(NO_ERROR, descFromParcel->readFromParcelable(parcelable));
diff --git a/media/libaudiohal/Android.bp b/media/libaudiohal/Android.bp
index 5f63e8d..f47dd0b 100644
--- a/media/libaudiohal/Android.bp
+++ b/media/libaudiohal/Android.bp
@@ -13,7 +13,7 @@
     srcs: [
         "DevicesFactoryHalInterface.cpp",
         "EffectsFactoryHalInterface.cpp",
-        "FactoryHalHidl.cpp",
+        "FactoryHal.cpp",
     ],
 
     cflags: [
@@ -28,10 +28,12 @@
         "libaudiohal@6.0",
         "libaudiohal@7.0",
         "libaudiohal@7.1",
+        "libaudiohal@aidl",
     ],
 
     shared_libs: [
         "audioclient-types-aidl-cpp",
+        "libbinder_ndk",
         "libdl",
         "libhidlbase",
         "liblog",
@@ -41,6 +43,7 @@
     header_libs: [
         "libaudiohal_headers",
         "libbase_headers",
+        "liberror_headers",
         "libmediautils_headers",
     ]
 }
@@ -65,15 +68,11 @@
 
     header_libs: [
         "libaudiohal_headers"
-    ]
+    ],
 }
 
 cc_library_headers {
     name: "libaudiohal_headers",
 
     export_include_dirs: ["include"],
-
-    // This is needed because the stream interface includes media/MicrophoneInfo.h
-    header_libs: ["av-headers"],
-    export_header_lib_headers: ["av-headers"],
 }
diff --git a/media/libaudiohal/DevicesFactoryHalInterface.cpp b/media/libaudiohal/DevicesFactoryHalInterface.cpp
index 5ad26fc..adce681 100644
--- a/media/libaudiohal/DevicesFactoryHalInterface.cpp
+++ b/media/libaudiohal/DevicesFactoryHalInterface.cpp
@@ -14,19 +14,14 @@
  * limitations under the License.
  */
 
-#include <string>
-
 #include <media/audiohal/DevicesFactoryHalInterface.h>
-#include <media/audiohal/FactoryHalHidl.h>
+#include <media/audiohal/FactoryHal.h>
 
 namespace android {
 
 // static
 sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
-    using namespace std::string_literals;
-    return createPreferredImpl<DevicesFactoryHalInterface>(
-            std::make_pair("android.hardware.audio"s, "IDevicesFactory"s),
-            std::make_pair("android.hardware.audio.effect"s, "IEffectsFactory"s));
+    return createPreferredImpl<DevicesFactoryHalInterface>(true /* isCore */);
 }
 
 } // namespace android
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index 8a28f64..3a05f21 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -14,19 +14,14 @@
  * limitations under the License.
  */
 
-#include <string>
-
 #include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <media/audiohal/FactoryHalHidl.h>
+#include <media/audiohal/FactoryHal.h>
 
 namespace android {
 
 // static
 sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
-    using namespace std::string_literals;
-    return createPreferredImpl<EffectsFactoryHalInterface>(
-            std::make_pair("android.hardware.audio.effect"s, "IEffectsFactory"s),
-            std::make_pair("android.hardware.audio"s, "IDevicesFactory"s));
+    return createPreferredImpl<EffectsFactoryHalInterface>(false /* isCore */);
 }
 
 // static
diff --git a/media/libaudiohal/FactoryHal.cpp b/media/libaudiohal/FactoryHal.cpp
new file mode 100644
index 0000000..f88915d
--- /dev/null
+++ b/media/libaudiohal/FactoryHal.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <map>
+#include <memory>
+#define LOG_TAG "FactoryHal"
+
+#include <algorithm>
+#include <array>
+#include <cstddef>
+#include <dlfcn.h>
+#include <utility>
+
+#include <android/binder_manager.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <utils/Log.h>
+
+#include "include/media/audiohal/AudioHalVersionInfo.h"
+#include "include/media/audiohal/FactoryHal.h"
+
+namespace android::detail {
+
+namespace {
+
+using ::android::detail::AudioHalVersionInfo;
+
+// The pair of the interface's package name and the interface name,
+// e.g. <"android.hardware.audio", "IDevicesFactory"> for HIDL, <"android.hardware.audio.core",
+// "IModule"> for AIDL.
+// Splitting is used for easier construction of versioned names (FQNs).
+using InterfaceName = std::pair<std::string, std::string>;
+
+/**
+ * Supported HAL versions, from most recent to least recent.
+ * This list need to keep sync with AudioHalVersionInfo.VERSIONS in
+ * media/java/android/media/AudioHalVersionInfo.java.
+ */
+static const std::array<AudioHalVersionInfo, 5> sAudioHALVersions = {
+    // TODO: remove this comment to get AIDL
+    // AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, 1, 0),
+    AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1),
+    AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 0),
+    AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0),
+    AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 5, 0),
+    AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 4, 0),
+};
+
+static const std::map<AudioHalVersionInfo::Type, InterfaceName> sDevicesHALInterfaces = {
+        {AudioHalVersionInfo::Type::AIDL, std::make_pair("android.hardware.audio.core", "IModule")},
+        {AudioHalVersionInfo::Type::HIDL,
+         std::make_pair("android.hardware.audio", "IDevicesFactory")},
+};
+
+static const std::map<AudioHalVersionInfo::Type, InterfaceName> sEffectsHALInterfaces = {
+        {AudioHalVersionInfo::Type::AIDL,
+         std::make_pair("android.hardware.audio.effect", "IFactory")},
+        {AudioHalVersionInfo::Type::HIDL,
+         std::make_pair("android.hardware.audio.effect", "IEffectsFactory")},
+};
+
+bool createHalService(const AudioHalVersionInfo& version, bool isDevice, void** rawInterface) {
+    const std::string libName = "libaudiohal@" + version.toVersionString() + ".so";
+    const std::string factoryFunctionName =
+            isDevice ? "createIDevicesFactory" : "createIEffectsFactory";
+    constexpr int dlMode = RTLD_LAZY;
+    void* handle = nullptr;
+    dlerror(); // clear
+    handle = dlopen(libName.c_str(), dlMode);
+    if (handle == nullptr) {
+        const char* error = dlerror();
+        ALOGE("Failed to dlopen %s: %s", libName.c_str(),
+                error != nullptr ? error : "unknown error");
+        return false;
+    }
+    void* (*factoryFunction)();
+    *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
+    if (!factoryFunction) {
+        const char* error = dlerror();
+        ALOGE("Factory function %s not found in library %s: %s",
+                factoryFunctionName.c_str(), libName.c_str(),
+                error != nullptr ? error : "unknown error");
+        dlclose(handle);
+        return false;
+    }
+    *rawInterface = (*factoryFunction)();
+    ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
+            factoryFunctionName.c_str(), libName.c_str());
+    return true;
+}
+
+bool hasAidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+    const std::string name = interface.first + "." + interface.second + "/default";
+    const bool isDeclared = AServiceManager_isDeclared(name.c_str());
+    if (!isDeclared) {
+        ALOGW("%s %s: false", __func__, name.c_str());
+        return false;
+    }
+    ALOGI("%s %s: true, version %s", __func__, name.c_str(), version.toString().c_str());
+    return true;
+}
+
+bool hasHidlHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+    using ::android::hidl::manager::V1_0::IServiceManager;
+    sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
+    if (!sm) {
+        ALOGW("Failed to obtain HIDL ServiceManager");
+        return false;
+    }
+    // Since audio HAL doesn't support multiple clients, avoid instantiating
+    // the interface right away. Instead, query the transport type for it.
+    using ::android::hardware::Return;
+    using Transport = IServiceManager::Transport;
+    const std::string fqName =
+            interface.first + "@" + version.toVersionString() + "::" + interface.second;
+    const std::string instance = "default";
+    Return<Transport> transport = sm->getTransport(fqName, instance);
+    if (!transport.isOk()) {
+        ALOGW("Failed to obtain transport type for %s/%s: %s",
+              fqName.c_str(), instance.c_str(), transport.description().c_str());
+        return false;
+    }
+    return transport != Transport::EMPTY;
+}
+
+bool hasHalService(const InterfaceName& interface, const AudioHalVersionInfo& version) {
+    auto halType = version.getType();
+    if (halType == AudioHalVersionInfo::Type::AIDL) {
+        return hasAidlHalService(interface, version);
+    } else if (halType == AudioHalVersionInfo::Type::HIDL) {
+        return hasHidlHalService(interface, version);
+    } else {
+        ALOGE("HalType not supported %s", version.toString().c_str());
+        return false;
+    }
+}
+
+}  // namespace
+
+void *createPreferredImpl(bool isDevice) {
+    auto findMostRecentVersion = [](const auto& iMap) {
+        return std::find_if(sAudioHALVersions.begin(), sAudioHALVersions.end(),
+                            [iMap](const auto& v) {
+                                auto iface = iMap.find(v.getType());
+                                return hasHalService(iface->second, v);
+                            });
+    };
+
+    auto interfaceMap = isDevice ? sDevicesHALInterfaces : sEffectsHALInterfaces;
+    auto siblingInterfaceMap = isDevice ? sEffectsHALInterfaces : sDevicesHALInterfaces;
+    auto ifaceVersionIt = findMostRecentVersion(interfaceMap);
+    auto siblingVersionIt = findMostRecentVersion(siblingInterfaceMap);
+    if (ifaceVersionIt != sAudioHALVersions.end() && siblingVersionIt != sAudioHALVersions.end() &&
+        // same HAL type (HIDL/AIDL) and same major version
+        ifaceVersionIt->getType() == siblingVersionIt->getType() &&
+        ifaceVersionIt->getMajorVersion() == siblingVersionIt->getMajorVersion()) {
+        void* rawInterface;
+        if (createHalService(std::max(*ifaceVersionIt, *siblingVersionIt), isDevice,
+                             &rawInterface)) {
+            return rawInterface;
+        } else {
+            ALOGE("Failed to create HAL services with major %s, sibling %s!",
+                  ifaceVersionIt->toString().c_str(), siblingVersionIt->toString().c_str());
+        }
+    } else {
+        ALOGE("Found no HAL version, main(%s) %s %s!", isDevice ? "Device" : "Effect",
+              (ifaceVersionIt == sAudioHALVersions.end()) ? "null"
+                                                          : ifaceVersionIt->toString().c_str(),
+              (siblingVersionIt == sAudioHALVersions.end()) ? "null"
+                                                            : siblingVersionIt->toString().c_str());
+    }
+    return nullptr;
+}
+
+}  // namespace android::detail
diff --git a/media/libaudiohal/FactoryHalHidl.cpp b/media/libaudiohal/FactoryHalHidl.cpp
deleted file mode 100644
index 590fec5..0000000
--- a/media/libaudiohal/FactoryHalHidl.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "FactoryHalHidl"
-
-#include <algorithm>
-#include <array>
-#include <utility>
-
-#include <media/audiohal/FactoryHalHidl.h>
-
-#include <dlfcn.h>
-
-#include <android/hidl/manager/1.0/IServiceManager.h>
-#include <hidl/ServiceManagement.h>
-#include <hidl/Status.h>
-#include <utils/Log.h>
-
-namespace android::detail {
-
-namespace {
-/** Supported HAL versions, from most recent to least recent.
- */
-#define CONC_VERSION(maj, min) #maj "." #min
-#define DECLARE_VERSION(maj, min) std::make_pair(std::make_pair(maj, min), CONC_VERSION(maj, min))
-static constexpr std::array<std::pair<std::pair<int, int>, const char*>, 5> sAudioHALVersions = {
-    DECLARE_VERSION(7, 1),
-    DECLARE_VERSION(7, 0),
-    DECLARE_VERSION(6, 0),
-    DECLARE_VERSION(5, 0),
-    DECLARE_VERSION(4, 0)
-};
-
-bool createHalService(const std::string& version, const std::string& interface,
-        void** rawInterface) {
-    const std::string libName = "libaudiohal@" + version + ".so";
-    const std::string factoryFunctionName = "create" + interface;
-    constexpr int dlMode = RTLD_LAZY;
-    void* handle = nullptr;
-    dlerror(); // clear
-    handle = dlopen(libName.c_str(), dlMode);
-    if (handle == nullptr) {
-        const char* error = dlerror();
-        ALOGE("Failed to dlopen %s: %s", libName.c_str(),
-                error != nullptr ? error : "unknown error");
-        return false;
-    }
-    void* (*factoryFunction)();
-    *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
-    if (!factoryFunction) {
-        const char* error = dlerror();
-        ALOGE("Factory function %s not found in library %s: %s",
-                factoryFunctionName.c_str(), libName.c_str(),
-                error != nullptr ? error : "unknown error");
-        dlclose(handle);
-        return false;
-    }
-    *rawInterface = (*factoryFunction)();
-    ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
-            factoryFunctionName.c_str(), libName.c_str());
-    return true;
-}
-
-bool hasHalService(const std::string& package, const std::string& version,
-        const std::string& interface) {
-    using ::android::hidl::manager::V1_0::IServiceManager;
-    sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
-    if (!sm) {
-        ALOGE("Failed to obtain HIDL ServiceManager");
-        return false;
-    }
-    // Since audio HAL doesn't support multiple clients, avoid instantiating
-    // the interface right away. Instead, query the transport type for it.
-    using ::android::hardware::Return;
-    using Transport = IServiceManager::Transport;
-    const std::string fqName = package + "@" + version + "::" + interface;
-    const std::string instance = "default";
-    Return<Transport> transport = sm->getTransport(fqName, instance);
-    if (!transport.isOk()) {
-        ALOGE("Failed to obtain transport type for %s/%s: %s",
-                fqName.c_str(), instance.c_str(), transport.description().c_str());
-        return false;
-    }
-    return transport != Transport::EMPTY;
-}
-
-}  // namespace
-
-void* createPreferredImpl(const InterfaceName& iface, const InterfaceName& siblingIface) {
-    auto findMostRecentVersion = [](const InterfaceName& iface) {
-        return std::find_if(detail::sAudioHALVersions.begin(), detail::sAudioHALVersions.end(),
-                [&](const auto& v) { return hasHalService(iface.first, v.second, iface.second); });
-    };
-    auto ifaceVersionIt = findMostRecentVersion(iface);
-    auto siblingVersionIt = findMostRecentVersion(siblingIface);
-    if (ifaceVersionIt != detail::sAudioHALVersions.end() &&
-            siblingVersionIt != detail::sAudioHALVersions.end() &&
-            // same major version
-            ifaceVersionIt->first.first == siblingVersionIt->first.first) {
-        std::string libraryVersion =
-                ifaceVersionIt->first >= siblingVersionIt->first ?
-                ifaceVersionIt->second : siblingVersionIt->second;
-        void* rawInterface;
-        if (createHalService(libraryVersion, iface.second, &rawInterface)) {
-            return rawInterface;
-        }
-    }
-    return nullptr;
-}
-
-}  // namespace android::detail
diff --git a/media/libaudiohal/impl/Android.bp b/media/libaudiohal/impl/Android.bp
index d30883a..d5f6598 100644
--- a/media/libaudiohal/impl/Android.bp
+++ b/media/libaudiohal/impl/Android.bp
@@ -12,13 +12,14 @@
     srcs: [
         "CoreConversionHelperHidl.cpp",
         "DeviceHalHidl.cpp",
+        "DevicesFactoryHalEntry.cpp",
         "DevicesFactoryHalHidl.cpp",
         "StreamHalHidl.cpp",
     ],
 }
 
 filegroup {
-    name: "audio_effect_hal_client_sources",
+    name: "audio_effect_hidl_hal_client_sources",
     srcs: [
         "EffectBufferHalHidl.cpp",
         "EffectConversionHelperHidl.cpp",
@@ -28,6 +29,21 @@
 }
 
 cc_defaults {
+    name: "libaudiohal_hidl_default",
+    shared_libs: [
+        "android.hardware.audio.common-util",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libaudiohal_deathhandler",
+        "libhidlbase",
+        "libhidlmemory",
+    ],
+    header_libs: [
+        "android.hardware.audio.common.util@all-versions",
+    ]
+}
+
+cc_defaults {
     name: "libaudiohal_default",
 
     cflags: [
@@ -37,31 +53,28 @@
         "-fvisibility=hidden",
     ],
     shared_libs: [
-        "android.hardware.audio.common-util",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
+        "audioclient-types-aidl-cpp",
         "av-types-aidl-cpp",
+        "libaudioclient_aidl_conversion",
         "libaudiofoundation",
-        "libaudiohal_deathhandler",
         "libaudioutils",
         "libbase",
         "libbinder",
         "libcutils",
         "libfmq",
         "libhardware",
-        "libhidlbase",
-        "libhidlmemory",
         "liblog",
         "libmedia_helper",
         "libmediautils",
         "libutils",
-        "audioclient-types-aidl-cpp",
     ],
     header_libs: [
-        "android.hardware.audio.common.util@all-versions",
         "libaudioclient_headers",
         "libaudiohal_headers"
     ],
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_export_shared",
+    ],
 
     export_shared_lib_headers: [
         "libfmq",
@@ -70,11 +83,14 @@
 
 cc_library_shared {
     name: "libaudiohal@4.0",
-    defaults: ["libaudiohal_default"],
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_hidl_default"
+    ],
     srcs: [
         ":audio_core_hal_client_sources",
-        ":audio_effect_hal_client_sources",
-        "EffectsFactoryHalHidlEntry.cpp",
+        ":audio_effect_hidl_hal_client_sources",
+        "EffectsFactoryHalEntry.cpp",
     ],
     shared_libs: [
         "android.hardware.audio.common@4.0",
@@ -93,11 +109,14 @@
 
 cc_library_shared {
     name: "libaudiohal@5.0",
-    defaults: ["libaudiohal_default"],
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_hidl_default"
+    ],
     srcs: [
         ":audio_core_hal_client_sources",
-        ":audio_effect_hal_client_sources",
-        "EffectsFactoryHalHidlEntry.cpp",
+        ":audio_effect_hidl_hal_client_sources",
+        "EffectsFactoryHalEntry.cpp",
     ],
     shared_libs: [
         "android.hardware.audio.common@5.0",
@@ -116,11 +135,14 @@
 
 cc_library_shared {
     name: "libaudiohal@6.0",
-    defaults: ["libaudiohal_default"],
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_hidl_default"
+    ],
     srcs: [
         ":audio_core_hal_client_sources",
-        ":audio_effect_hal_client_sources",
-        "EffectsFactoryHalHidlEntry.cpp",
+        ":audio_effect_hidl_hal_client_sources",
+        "EffectsFactoryHalEntry.cpp",
     ],
     shared_libs: [
         "android.hardware.audio.common@6.0",
@@ -139,9 +161,12 @@
 
 cc_library_static {
     name: "libaudiohal.effect@7.0",
-    defaults: ["libaudiohal_default"],
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_hidl_default"
+    ],
     srcs: [
-        ":audio_effect_hal_client_sources",
+        ":audio_effect_hidl_hal_client_sources",
     ],
     static_libs: [
         "android.hardware.audio.common@7.0",
@@ -158,10 +183,13 @@
 
 cc_library_shared {
     name: "libaudiohal@7.0",
-    defaults: ["libaudiohal_default"],
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_hidl_default"
+    ],
     srcs: [
         ":audio_core_hal_client_sources",
-        "EffectsFactoryHalHidlEntry.cpp",
+        "EffectsFactoryHalEntry.cpp",
     ],
     static_libs: [
         "android.hardware.audio.common@7.0",
@@ -182,10 +210,13 @@
 
 cc_library_shared {
     name: "libaudiohal@7.1",
-    defaults: ["libaudiohal_default"],
+    defaults: [
+        "libaudiohal_default",
+        "libaudiohal_hidl_default"
+    ],
     srcs: [
         ":audio_core_hal_client_sources",
-        "EffectsFactoryHalHidlEntry.cpp",
+        "EffectsFactoryHalEntry.cpp",
     ],
     static_libs: [
         "android.hardware.audio.common@7.0",
@@ -207,3 +238,62 @@
         "-include common/all-versions/VersionMacro.h",
     ]
 }
+
+cc_library_shared {
+    name: "libaudiohal@aidl",
+    defaults: [
+        "libaudiohal_default",
+        "latest_android_hardware_audio_common_ndk_shared",
+        "latest_android_hardware_audio_core_ndk_shared",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    srcs: [
+        "DeviceHalAidl.cpp",
+        "DevicesFactoryHalEntry.cpp",
+        "DevicesFactoryHalAidl.cpp",
+        "EffectConversionHelperAidl.cpp",
+        "EffectBufferHalAidl.cpp",
+        "EffectHalAidl.cpp",
+        "effectsAidlConversion/AidlConversionAec.cpp",
+        "effectsAidlConversion/AidlConversionAgc1.cpp",
+        "effectsAidlConversion/AidlConversionAgc2.cpp",
+        "effectsAidlConversion/AidlConversionBassBoost.cpp",
+        "effectsAidlConversion/AidlConversionDownmix.cpp",
+        "effectsAidlConversion/AidlConversionDynamicsProcessing.cpp",
+        "effectsAidlConversion/AidlConversionEnvReverb.cpp",
+        "effectsAidlConversion/AidlConversionEq.cpp",
+        "effectsAidlConversion/AidlConversionHapticGenerator.cpp",
+        "effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp",
+        "effectsAidlConversion/AidlConversionNoiseSuppression.cpp",
+        "effectsAidlConversion/AidlConversionPresetReverb.cpp",
+        "effectsAidlConversion/AidlConversionSpatializer.cpp",
+        "effectsAidlConversion/AidlConversionVendorExtension.cpp",
+        "effectsAidlConversion/AidlConversionVirtualizer.cpp",
+        "effectsAidlConversion/AidlConversionVisualizer.cpp",
+        "EffectsFactoryHalAidl.cpp",
+        "EffectsFactoryHalEntry.cpp",
+        "StreamHalAidl.cpp",
+    ],
+    static_libs: [
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+        "libaudio_aidl_conversion_common_cpp",
+        "libaudio_aidl_conversion_common_ndk",
+        "libaudio_aidl_conversion_effect_ndk",
+        "libaudioaidlcommon",
+    ],
+    header_libs: [
+        "libaudio_system_headers",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_CPP_NDK",
+    ],
+}
diff --git a/media/libaudiohal/impl/ConversionHelperAidl.h b/media/libaudiohal/impl/ConversionHelperAidl.h
new file mode 100644
index 0000000..db6b6cf
--- /dev/null
+++ b/media/libaudiohal/impl/ConversionHelperAidl.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class Args {
+  public:
+    explicit Args(const Vector<String16>& args)
+            : mValues(args.size()), mPtrs(args.size()) {
+        for (size_t i = 0; i < args.size(); ++i) {
+            mValues[i] = std::string(String8(args[i]));
+            mPtrs[i] = mValues[i].c_str();
+        }
+    }
+    const char** args() { return mPtrs.data(); }
+  private:
+    std::vector<std::string> mValues;
+    std::vector<const char*> mPtrs;
+};
+
+class ConversionHelperAidl {
+  protected:
+    ConversionHelperAidl(std::string_view className) : mClassName(className) {}
+
+    const std::string& getClassName() const {
+        return mClassName;
+    }
+
+    const std::string mClassName;
+};
+
+}  // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.cpp b/media/libaudiohal/impl/DeviceHalAidl.cpp
new file mode 100644
index 0000000..8b88f24
--- /dev/null
+++ b/media/libaudiohal/impl/DeviceHalAidl.cpp
@@ -0,0 +1,1115 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DeviceHalAidl"
+// #define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <forward_list>
+
+#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 <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <mediautils/TimeCheck.h>
+#include <Utils.h>
+#include <utils/Log.h>
+
+#include "DeviceHalAidl.h"
+#include "StreamHalAidl.h"
+
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::media::audio::common::AudioConfig;
+using aidl::android::media::audio::common::AudioDevice;
+using aidl::android::media::audio::common::AudioDeviceType;
+using aidl::android::media::audio::common::AudioInputFlags;
+using aidl::android::media::audio::common::AudioIoFlags;
+using aidl::android::media::audio::common::AudioLatencyMode;
+using aidl::android::media::audio::common::AudioMode;
+using aidl::android::media::audio::common::AudioOutputFlags;
+using aidl::android::media::audio::common::AudioPort;
+using aidl::android::media::audio::common::AudioPortConfig;
+using aidl::android::media::audio::common::AudioPortDeviceExt;
+using aidl::android::media::audio::common::AudioPortMixExt;
+using aidl::android::media::audio::common::AudioPortMixExtUseCase;
+using aidl::android::media::audio::common::AudioPortExt;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::Int;
+using aidl::android::media::audio::common::Float;
+using aidl::android::hardware::audio::common::getFrameSizeInBytes;
+using aidl::android::hardware::audio::common::isBitPositionFlagSet;
+using aidl::android::hardware::audio::common::makeBitPositionFlagMask;
+using aidl::android::media::audio::common::MicrophoneDynamicInfo;
+using aidl::android::media::audio::common::MicrophoneInfo;
+using aidl::android::hardware::audio::common::RecordTrackMetadata;
+using aidl::android::hardware::audio::core::AudioPatch;
+using aidl::android::hardware::audio::core::IModule;
+using aidl::android::hardware::audio::core::ITelephony;
+using aidl::android::hardware::audio::core::StreamDescriptor;
+
+namespace android {
+
+namespace {
+
+bool isConfigEqualToPortConfig(const AudioConfig& config, const AudioPortConfig& portConfig) {
+    return portConfig.sampleRate.value().value == config.base.sampleRate &&
+            portConfig.channelMask.value() == config.base.channelMask &&
+            portConfig.format.value() == config.base.format;
+}
+
+void setConfigFromPortConfig(AudioConfig* config, const AudioPortConfig& portConfig) {
+    config->base.sampleRate = portConfig.sampleRate.value().value;
+    config->base.channelMask = portConfig.channelMask.value();
+    config->base.format = portConfig.format.value();
+}
+
+void setPortConfigFromConfig(AudioPortConfig* portConfig, const AudioConfig& config) {
+    portConfig->sampleRate = Int{ .value = config.base.sampleRate };
+    portConfig->channelMask = config.base.channelMask;
+    portConfig->format = config.base.format;
+}
+
+}  // namespace
+
+status_t DeviceHalAidl::getSupportedDevices(uint32_t*) {
+    // Obsolete.
+    return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::initCheck() {
+    TIME_CHECK();
+    if (mModule == nullptr) return NO_INIT;
+    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());
+    std::transform(ports.begin(), ports.end(), std::inserter(mPorts, mPorts.end()),
+            [](const auto& p) { return std::make_pair(p.id, p); });
+    mDefaultInputPortId = mDefaultOutputPortId = -1;
+    const int defaultDeviceFlag = 1 << AudioPortDeviceExt::FLAG_INDEX_DEFAULT_DEVICE;
+    for (const auto& pair : mPorts) {
+        const auto& p = pair.second;
+        if (p.ext.getTag() == AudioPortExt::Tag::device &&
+                (p.ext.get<AudioPortExt::Tag::device>().flags & defaultDeviceFlag) != 0) {
+            if (p.flags.getTag() == AudioIoFlags::Tag::input) {
+                mDefaultInputPortId = p.id;
+            } else if (p.flags.getTag() == AudioIoFlags::Tag::output) {
+                mDefaultOutputPortId = p.id;
+            }
+        }
+    }
+    ALOGI("%s: module %s default port ids: input %d, output %d",
+            __func__, mInstance.c_str(), mDefaultInputPortId, mDefaultOutputPortId);
+    std::vector<AudioPortConfig> portConfigs;
+    RETURN_STATUS_IF_ERROR(
+            statusTFromBinderStatus(mModule->getAudioPortConfigs(&portConfigs)));  // OK if empty
+    std::transform(portConfigs.begin(), portConfigs.end(),
+            std::inserter(mPortConfigs, mPortConfigs.end()),
+            [](const auto& p) { return std::make_pair(p.id, p); });
+    std::vector<AudioPatch> patches;
+    RETURN_STATUS_IF_ERROR(
+            statusTFromBinderStatus(mModule->getAudioPatches(&patches)));  // OK if empty
+    std::transform(patches.begin(), patches.end(),
+            std::inserter(mPatches, mPatches.end()),
+            [](const auto& p) { return std::make_pair(p.id, p); });
+    return OK;
+}
+
+status_t DeviceHalAidl::setVoiceVolume(float volume) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    std::shared_ptr<ITelephony> telephony;
+    if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
+            status.isOk() && telephony != nullptr) {
+        ITelephony::TelecomConfig inConfig{ .voiceVolume = Float{volume} }, outConfig;
+        RETURN_STATUS_IF_ERROR(
+                statusTFromBinderStatus(telephony->setTelecomConfig(inConfig, &outConfig)));
+        ALOGW_IF(outConfig.voiceVolume.has_value() && volume != outConfig.voiceVolume.value().value,
+                "%s: the resulting voice volume %f is not the same as requested %f",
+                __func__, outConfig.voiceVolume.value().value, volume);
+    }
+    return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::setMasterVolume(float volume) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return statusTFromBinderStatus(mModule->setMasterVolume(volume));
+}
+
+status_t DeviceHalAidl::getMasterVolume(float *volume) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return statusTFromBinderStatus(mModule->getMasterVolume(volume));
+}
+
+status_t DeviceHalAidl::setMode(audio_mode_t mode) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    AudioMode audioMode = VALUE_OR_FATAL(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
+    std::shared_ptr<ITelephony> telephony;
+    if (ndk::ScopedAStatus status = mModule->getTelephony(&telephony);
+            status.isOk() && telephony != nullptr) {
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(telephony->switchAudioMode(audioMode)));
+    }
+    return statusTFromBinderStatus(mModule->updateAudioMode(audioMode));
+}
+
+status_t DeviceHalAidl::setMicMute(bool state) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return statusTFromBinderStatus(mModule->setMicMute(state));
+}
+
+status_t DeviceHalAidl::getMicMute(bool *state) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return statusTFromBinderStatus(mModule->getMicMute(state));
+}
+
+status_t DeviceHalAidl::setMasterMute(bool state) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return statusTFromBinderStatus(mModule->setMasterMute(state));
+}
+
+status_t DeviceHalAidl::getMasterMute(bool *state) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return statusTFromBinderStatus(mModule->getMasterMute(state));
+}
+
+status_t DeviceHalAidl::setParameters(const String8& kvPairs __unused) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t DeviceHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+    TIME_CHECK();
+    values->clear();
+    if (!mModule) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+namespace {
+
+class Cleanup {
+  public:
+    typedef void (DeviceHalAidl::*Cleaner)(int32_t);
+
+    Cleanup(DeviceHalAidl* device, Cleaner cleaner, int32_t id) :
+            mDevice(device), mCleaner(cleaner), mId(id) {}
+    ~Cleanup() { clean(); }
+    void clean() {
+        if (mDevice != nullptr) (mDevice->*mCleaner)(mId);
+        disarm();
+    }
+    void disarm() { mDevice = nullptr; }
+
+  private:
+    DeviceHalAidl* mDevice;
+    const Cleaner mCleaner;
+    const int32_t mId;
+};
+
+}  // namespace
+
+// Since the order of container elements destruction is unspecified,
+// ensure that cleanups are performed from the most recent one and upwards.
+// This is the same as if there were individual Cleanup instances on the stack,
+// however the bonus is that we can disarm all of them with just one statement.
+class DeviceHalAidl::Cleanups : public std::forward_list<Cleanup> {
+  public:
+    ~Cleanups() { for (auto& c : *this) c.clean(); }
+    void disarmAll() { for (auto& c : *this) c.disarm(); }
+};
+
+status_t DeviceHalAidl::getInputBufferSize(const struct audio_config* config, size_t* size) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (size == nullptr) return BAD_VALUE;
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
+    AudioDevice aidlDevice;
+    aidlDevice.type.type = AudioDeviceType::IN_DEFAULT;
+    AudioSource aidlSource = AudioSource::DEFAULT;
+    AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(0);
+    AudioPortConfig mixPortConfig;
+    Cleanups cleanups;
+    audio_config writableConfig = *config;
+    int32_t nominalLatency;
+    RETURN_STATUS_IF_ERROR(prepareToOpenStream(0 /*handle*/, aidlDevice, aidlFlags, aidlSource,
+                    &writableConfig, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+    *size = aidlConfig.frameCount *
+            getFrameSizeInBytes(aidlConfig.base.format, aidlConfig.base.channelMask);
+    // Do not disarm cleanups to release temporary port configs.
+    return OK;
+}
+
+status_t DeviceHalAidl::prepareToOpenStream(
+        int32_t aidlHandle, const AudioDevice& aidlDevice, const AudioIoFlags& aidlFlags,
+        AudioSource aidlSource, struct audio_config* config,
+        Cleanups* cleanups, AudioConfig* aidlConfig, AudioPortConfig* mixPortConfig,
+        int32_t* nominalLatency) {
+    const bool isInput = aidlFlags.getTag() == AudioIoFlags::Tag::input;
+    // Find / create AudioPortConfigs for the device port and the mix port,
+    // then find / create a patch between them, and open a stream on the mix port.
+    AudioPortConfig devicePortConfig;
+    bool created = false;
+    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(aidlDevice, &devicePortConfig, &created));
+    if (created) {
+        cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, devicePortConfig.id);
+    }
+    RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(*aidlConfig, aidlFlags, aidlHandle, aidlSource,
+                    mixPortConfig, &created));
+    if (created) {
+        cleanups->emplace_front(this, &DeviceHalAidl::resetPortConfig, mixPortConfig->id);
+    }
+    setConfigFromPortConfig(aidlConfig, *mixPortConfig);
+    AudioPatch patch;
+    if (isInput) {
+        RETURN_STATUS_IF_ERROR(findOrCreatePatch(
+                        {devicePortConfig.id}, {mixPortConfig->id}, &patch, &created));
+    } else {
+        RETURN_STATUS_IF_ERROR(findOrCreatePatch(
+                        {mixPortConfig->id}, {devicePortConfig.id}, &patch, &created));
+    }
+    if (created) {
+        cleanups->emplace_front(this, &DeviceHalAidl::resetPatch, patch.id);
+    }
+    *nominalLatency = patch.latenciesMs[0];
+    if (aidlConfig->frameCount <= 0) {
+        aidlConfig->frameCount = patch.minimumStreamBufferSizeFrames;
+    }
+    *config = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioConfig_audio_config_t(*aidlConfig, isInput));
+    return OK;
+}
+
+namespace {
+
+class StreamCallbackBase {
+  protected:
+    explicit StreamCallbackBase(const sp<CallbackBroker>& broker) : mBroker(broker) {}
+  public:
+    void* getCookie() const { return mCookie; }
+    void setCookie(void* cookie) { mCookie = cookie; }
+    sp<CallbackBroker> getBroker() const {
+        if (void* cookie = mCookie; cookie != nullptr) return mBroker.promote();
+        return nullptr;
+    }
+  private:
+    const wp<CallbackBroker> mBroker;
+    std::atomic<void*> mCookie;
+};
+
+template<class C>
+class StreamCallbackBaseHelper {
+  protected:
+    explicit StreamCallbackBaseHelper(const StreamCallbackBase& base) : mBase(base) {}
+    sp<C> getCb(const sp<CallbackBroker>& broker, void* cookie);
+    using CbRef = const sp<C>&;
+    ndk::ScopedAStatus runCb(const std::function<void(CbRef cb)>& f) {
+        if (auto cb = getCb(mBase.getBroker(), mBase.getCookie()); cb != nullptr) f(cb);
+        return ndk::ScopedAStatus::ok();
+    }
+  private:
+    const StreamCallbackBase& mBase;
+};
+
+template<>
+sp<StreamOutHalInterfaceCallback> StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>::getCb(
+        const sp<CallbackBroker>& broker, void* cookie) {
+    if (broker != nullptr) return broker->getStreamOutCallback(cookie);
+    return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceEventCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::getCb(
+        const sp<CallbackBroker>& broker, void* cookie) {
+    if (broker != nullptr) return broker->getStreamOutEventCallback(cookie);
+    return nullptr;
+}
+
+template<>
+sp<StreamOutHalInterfaceLatencyModeCallback>
+StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::getCb(
+        const sp<CallbackBroker>& broker, void* cookie) {
+    if (broker != nullptr) return broker->getStreamOutLatencyModeCallback(cookie);
+    return nullptr;
+}
+
+/*
+Note on the callback ownership.
+
+In the Binder ownership model, the server implementation is kept alive
+as long as there is any client (proxy object) alive. This is done by
+incrementing the refcount of the server-side object by the Binder framework.
+When it detects that the last client is gone, it decrements the refcount back.
+
+Thus, it is not needed to keep any references to StreamCallback on our
+side (after we have sent an instance to the client), because we are
+the server-side. The callback object will be kept alive as long as the HAL server
+holds a strong ref to IStreamCallback proxy.
+*/
+
+class OutputStreamCallbackAidl : public StreamCallbackBase,
+                             public StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>,
+                             public ::aidl::android::hardware::audio::core::BnStreamCallback {
+  public:
+    explicit OutputStreamCallbackAidl(const sp<CallbackBroker>& broker)
+            : StreamCallbackBase(broker),
+              StreamCallbackBaseHelper<StreamOutHalInterfaceCallback>(
+                      *static_cast<StreamCallbackBase*>(this)) {}
+    ndk::ScopedAStatus onTransferReady() override {
+        return runCb([](CbRef cb) { cb->onWriteReady(); });
+    }
+    ndk::ScopedAStatus onError() override {
+        return runCb([](CbRef cb) { cb->onError(); });
+    }
+    ndk::ScopedAStatus onDrainReady() override {
+        return runCb([](CbRef cb) { cb->onDrainReady(); });
+    }
+};
+
+class OutputStreamEventCallbackAidl :
+            public StreamCallbackBase,
+            public StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>,
+            public StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>,
+            public ::aidl::android::hardware::audio::core::BnStreamOutEventCallback {
+  public:
+    explicit OutputStreamEventCallbackAidl(const sp<CallbackBroker>& broker)
+            : StreamCallbackBase(broker),
+              StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>(
+                      *static_cast<StreamCallbackBase*>(this)),
+              StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>(
+                      *static_cast<StreamCallbackBase*>(this)) {}
+    ndk::ScopedAStatus onCodecFormatChanged(const std::vector<uint8_t>& in_audioMetadata) override {
+        std::basic_string<uint8_t> halMetadata(in_audioMetadata.begin(), in_audioMetadata.end());
+        return StreamCallbackBaseHelper<StreamOutHalInterfaceEventCallback>::runCb(
+                [&halMetadata](auto cb) { cb->onCodecFormatChanged(halMetadata); });
+    }
+    ndk::ScopedAStatus onRecommendedLatencyModeChanged(
+            const std::vector<AudioLatencyMode>& in_modes) override {
+        auto halModes = VALUE_OR_FATAL(
+                ::aidl::android::convertContainer<std::vector<audio_latency_mode_t>>(
+                        in_modes,
+                        ::aidl::android::aidl2legacy_AudioLatencyMode_audio_latency_mode_t));
+        return StreamCallbackBaseHelper<StreamOutHalInterfaceLatencyModeCallback>::runCb(
+                [&halModes](auto cb) { cb->onRecommendedLatencyModeChanged(halModes); });
+    }
+};
+
+}  // namespace
+
+status_t DeviceHalAidl::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) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (!outStream || !config) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
+    AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, false /*isInput*/));
+    AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
+            ::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));
+    AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::output>(aidlOutputFlags);
+    AudioPortConfig mixPortConfig;
+    Cleanups cleanups;
+    int32_t nominalLatency;
+    RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags,
+                    AudioSource::SYS_RESERVED_INVALID /*only needed for input*/,
+                    config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+    ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamArguments args;
+    args.portConfigId = mixPortConfig.id;
+    const bool isOffload = isBitPositionFlagSet(
+            aidlOutputFlags, AudioOutputFlags::COMPRESS_OFFLOAD);
+    std::shared_ptr<OutputStreamCallbackAidl> streamCb;
+    if (isOffload) {
+        streamCb = ndk::SharedRefBase::make<OutputStreamCallbackAidl>(this);
+    }
+    auto eventCb = ndk::SharedRefBase::make<OutputStreamEventCallbackAidl>(this);
+    if (isOffload) {
+        args.offloadInfo = aidlConfig.offloadInfo;
+        args.callback = streamCb;
+    }
+    args.bufferSizeFrames = aidlConfig.frameCount;
+    args.eventCallback = eventCb;
+    ::aidl::android::hardware::audio::core::IModule::OpenOutputStreamReturn ret;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->openOutputStream(args, &ret)));
+    StreamContextAidl context(ret.desc, isOffload);
+    if (!context.isValid()) {
+        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
+                __func__, ret.desc.toString().c_str());
+        return NO_INIT;
+    }
+    *outStream = sp<StreamOutHalAidl>::make(*config, std::move(context), nominalLatency,
+            std::move(ret.stream), this /*callbackBroker*/);
+    void* cbCookie = (*outStream).get();
+    {
+        std::lock_guard l(mLock);
+        mCallbacks.emplace(cbCookie, Callbacks{});
+    }
+    if (streamCb) streamCb->setCookie(cbCookie);
+    eventCb->setCookie(cbCookie);
+    cleanups.disarmAll();
+    return OK;
+}
+
+status_t DeviceHalAidl::openInputStream(
+        audio_io_handle_t handle, audio_devices_t devices,
+        struct audio_config* config, audio_input_flags_t flags,
+        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__);
+    if (!inStream || !config) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    int32_t aidlHandle = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_io_handle_t_int32_t(handle));
+    AudioConfig aidlConfig = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_config_t_AudioConfig(*config, true /*isInput*/));
+    AudioDevice aidlDevice = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_device_AudioDevice(devices, address));
+    int32_t aidlInputFlags = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_input_flags_t_int32_t_mask(flags));
+    AudioIoFlags aidlFlags = AudioIoFlags::make<AudioIoFlags::Tag::input>(aidlInputFlags);
+    AudioSource aidlSource = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
+    AudioPortConfig mixPortConfig;
+    Cleanups cleanups;
+    int32_t nominalLatency;
+    RETURN_STATUS_IF_ERROR(prepareToOpenStream(aidlHandle, aidlDevice, aidlFlags, aidlSource,
+                    config, &cleanups, &aidlConfig, &mixPortConfig, &nominalLatency));
+    ::aidl::android::hardware::audio::core::IModule::OpenInputStreamArguments args;
+    args.portConfigId = mixPortConfig.id;
+    RecordTrackMetadata aidlTrackMetadata{
+        .source = aidlSource, .gain = 1, .channelMask = aidlConfig.base.channelMask };
+    if (outputDevice != AUDIO_DEVICE_NONE) {
+        aidlTrackMetadata.destinationDevice = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_device_AudioDevice(
+                    outputDevice, outputDeviceAddress));
+    }
+    args.sinkMetadata.tracks.push_back(std::move(aidlTrackMetadata));
+    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*/);
+    if (!context.isValid()) {
+        ALOGE("%s: Failed to created a valid stream context from the descriptor: %s",
+                __func__, ret.desc.toString().c_str());
+        return NO_INIT;
+    }
+    *inStream = sp<StreamInHalAidl>::make(*config, std::move(context), nominalLatency,
+            std::move(ret.stream), this /*micInfoProvider*/);
+    cleanups.disarmAll();
+    return OK;
+}
+
+status_t DeviceHalAidl::supportsAudioPatches(bool* supportsPatches) {
+    *supportsPatches = true;
+    return OK;
+}
+
+status_t DeviceHalAidl::createAudioPatch(unsigned int num_sources,
+                                         const struct audio_port_config* sources,
+                                         unsigned int num_sinks,
+                                         const struct audio_port_config* sinks,
+                                         audio_patch_handle_t* patch) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    if (num_sinks > AUDIO_PATCH_PORTS_MAX || num_sources > AUDIO_PATCH_PORTS_MAX ||
+        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
+    // a HAL module, the framework generates a globally unique handle, and maps
+    // it on the <HAL module, patch handle> pair.
+    // When the patch handle is set, it meant the framework intends to update
+    // an existing patch.
+    //
+    // This behavior corresponds to HAL module behavior, with the only difference
+    // that the HAL module uses `int32_t` for patch IDs. The following assert ensures
+    // that both the framework and the HAL use the same value for "no ID":
+    static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
+    int32_t halPatchId = static_cast<int32_t>(*patch);
+
+    // Upon conversion, mix port configs contain audio configuration, while
+    // device port configs contain device address. This data is used to find
+    // or create HAL configs.
+    std::vector<AudioPortConfig> aidlSources, aidlSinks;
+    for (unsigned int i = 0; i < num_sources; ++i) {
+        bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+                        sources[i].role, sources[i].type)) ==
+                ::aidl::android::AudioPortDirection::INPUT;
+        aidlSources.push_back(VALUE_OR_RETURN_STATUS(
+                        ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+                                sources[i], isInput, 0)));
+    }
+    for (unsigned int i = 0; i < num_sinks; ++i) {
+        bool isInput = VALUE_OR_RETURN_STATUS(::aidl::android::portDirection(
+                        sinks[i].role, sinks[i].type)) ==
+                ::aidl::android::AudioPortDirection::INPUT;
+        aidlSinks.push_back(VALUE_OR_RETURN_STATUS(
+                        ::aidl::android::legacy2aidl_audio_port_config_AudioPortConfig(
+                                sinks[i], isInput, 0)));
+    }
+    Cleanups cleanups;
+    auto existingPatchIt = halPatchId != 0 ? mPatches.find(halPatchId): mPatches.end();
+    AudioPatch aidlPatch;
+    if (existingPatchIt != mPatches.end()) {
+        aidlPatch = existingPatchIt->second;
+        aidlPatch.sourcePortConfigIds.clear();
+        aidlPatch.sinkPortConfigIds.clear();
+    }
+    ALOGD("%s: sources: %s, sinks: %s",
+            __func__, ::android::internal::ToString(aidlSources).c_str(),
+            ::android::internal::ToString(aidlSinks).c_str());
+    auto fillPortConfigs = [&](
+            const std::vector<AudioPortConfig>& configs, std::vector<int32_t>* ids) -> status_t {
+        for (const auto& s : configs) {
+            AudioPortConfig portConfig;
+            bool created = false;
+            RETURN_STATUS_IF_ERROR(findOrCreatePortConfig(s, &portConfig, &created));
+            if (created) {
+                cleanups.emplace_front(this, &DeviceHalAidl::resetPortConfig, portConfig.id);
+            }
+            ids->push_back(portConfig.id);
+        }
+        return OK;
+    };
+    RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSources, &aidlPatch.sourcePortConfigIds));
+    RETURN_STATUS_IF_ERROR(fillPortConfigs(aidlSinks, &aidlPatch.sinkPortConfigIds));
+    if (existingPatchIt != mPatches.end()) {
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+                        mModule->setAudioPatch(aidlPatch, &aidlPatch)));
+        existingPatchIt->second = aidlPatch;
+    } else {
+        bool created = false;
+        RETURN_STATUS_IF_ERROR(findOrCreatePatch(aidlPatch, &aidlPatch, &created));
+        // Since no cleanup of the patch is needed, 'created' is ignored.
+        halPatchId = aidlPatch.id;
+        *patch = static_cast<audio_patch_handle_t>(halPatchId);
+    }
+    cleanups.disarmAll();
+    return OK;
+}
+
+status_t DeviceHalAidl::releaseAudioPatch(audio_patch_handle_t patch) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    static_assert(AUDIO_PATCH_HANDLE_NONE == 0);
+    if (patch == AUDIO_PATCH_HANDLE_NONE) {
+        return BAD_VALUE;
+    }
+    int32_t halPatchId = static_cast<int32_t>(patch);
+    auto patchIt = mPatches.find(halPatchId);
+    if (patchIt == mPatches.end()) {
+        ALOGE("%s: patch with id %d not found", __func__, halPatchId);
+        return BAD_VALUE;
+    }
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->resetAudioPatch(halPatchId)));
+    mPatches.erase(patchIt);
+    return OK;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port* port __unused) {
+    TIME_CHECK();
+    ALOGE("%s not implemented yet", __func__);
+    return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::getAudioPort(struct audio_port_v7 *port __unused) {
+    TIME_CHECK();
+    ALOGE("%s not implemented yet", __func__);
+    return INVALID_OPERATION;
+}
+
+status_t DeviceHalAidl::setAudioPortConfig(const struct audio_port_config* config __unused) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+MicrophoneInfoProvider::Info const* DeviceHalAidl::getMicrophoneInfo() {
+    if (mMicrophones.status == Microphones::Status::UNKNOWN) {
+        TIME_CHECK();
+        std::vector<MicrophoneInfo> aidlInfo;
+        status_t status = statusTFromBinderStatus(mModule->getMicrophones(&aidlInfo));
+        if (status == OK) {
+            mMicrophones.status = Microphones::Status::QUERIED;
+            mMicrophones.info = std::move(aidlInfo);
+        } else if (status == INVALID_OPERATION) {
+            mMicrophones.status = Microphones::Status::NOT_SUPPORTED;
+        } else {
+            ALOGE("%s: Unexpected status from 'IModule.getMicrophones': %d", __func__, status);
+            return {};
+        }
+    }
+    if (mMicrophones.status == Microphones::Status::QUERIED) {
+        return &mMicrophones.info;
+    }
+    return {};  // NOT_SUPPORTED
+}
+
+status_t DeviceHalAidl::getMicrophones(
+        std::vector<audio_microphone_characteristic_t>* microphones) {
+    if (!microphones) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    auto staticInfo = getMicrophoneInfo();
+    if (!staticInfo) return INVALID_OPERATION;
+    std::vector<MicrophoneDynamicInfo> emptyDynamicInfo;
+    emptyDynamicInfo.reserve(staticInfo->size());
+    std::transform(staticInfo->begin(), staticInfo->end(), std::back_inserter(emptyDynamicInfo),
+            [](const auto& info) { return MicrophoneDynamicInfo{ .id = info.id }; });
+    *microphones = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::convertContainers<std::vector<audio_microphone_characteristic_t>>(
+                    *staticInfo, emptyDynamicInfo,
+                    ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t)
+    );
+    return OK;
+}
+
+status_t DeviceHalAidl::addDeviceEffect(audio_port_handle_t device __unused,
+        sp<EffectHalInterface> effect) {
+    if (!effect) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+status_t DeviceHalAidl::removeDeviceEffect(audio_port_handle_t device __unused,
+                            sp<EffectHalInterface> effect) {
+    if (!effect) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t DeviceHalAidl::getMmapPolicyInfos(
+        media::audio::common::AudioMMapPolicyType policyType __unused,
+        std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos __unused) {
+    TIME_CHECK();
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+int32_t DeviceHalAidl::getAAudioMixerBurstCount() {
+    TIME_CHECK();
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+int32_t DeviceHalAidl::getAAudioHardwareBurstMinUsec() {
+    TIME_CHECK();
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+error::Result<audio_hw_sync_t> DeviceHalAidl::getHwAvSync() {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    int32_t aidlHwAvSync;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->generateHwAvSyncId(&aidlHwAvSync)));
+    return VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_int32_t_audio_hw_sync_t(aidlHwAvSync));
+}
+
+status_t DeviceHalAidl::dump(int fd, const Vector<String16>& args) {
+    TIME_CHECK();
+    if (!mModule) return NO_INIT;
+    return mModule->dump(fd, Args(args).args(), args.size());
+};
+
+int32_t DeviceHalAidl::supportsBluetoothVariableLatency(bool* supports __unused) {
+    TIME_CHECK();
+    ALOGE("%s not implemented yet", __func__);
+    return INVALID_OPERATION;
+}
+
+bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPort& p) {
+    if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
+    return p.ext.get<AudioPortExt::Tag::device>().device == device;
+}
+
+bool DeviceHalAidl::audioDeviceMatches(const AudioDevice& device, const AudioPortConfig& p) {
+    if (p.ext.getTag() != AudioPortExt::Tag::device) return false;
+    if (device.type.type == AudioDeviceType::IN_DEFAULT) {
+        return p.portId == mDefaultInputPortId;
+    } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
+        return p.portId == mDefaultOutputPortId;
+    }
+    return p.ext.get<AudioPortExt::Tag::device>().device == device;
+}
+
+status_t DeviceHalAidl::createPortConfig(
+        const AudioPortConfig& requestedPortConfig, PortConfigs::iterator* result) {
+    TIME_CHECK();
+    AudioPortConfig appliedPortConfig;
+    bool applied = false;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
+                            requestedPortConfig, &appliedPortConfig, &applied)));
+    if (!applied) {
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPortConfig(
+                                appliedPortConfig, &appliedPortConfig, &applied)));
+        if (!applied) {
+            ALOGE("%s: module %s did not apply suggested config %s",
+                    __func__, mInstance.c_str(), appliedPortConfig.toString().c_str());
+            return NO_INIT;
+        }
+    }
+    auto id = appliedPortConfig.id;
+    auto [it, inserted] = mPortConfigs.emplace(std::move(id), std::move(appliedPortConfig));
+    LOG_ALWAYS_FATAL_IF(!inserted, "%s: port config with id %d already exists",
+            __func__, it->first);
+    *result = it;
+    return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePatch(
+        const AudioPatch& requestedPatch, AudioPatch* patch, bool* created) {
+    std::set<int32_t> sourcePortConfigIds(requestedPatch.sourcePortConfigIds.begin(),
+            requestedPatch.sourcePortConfigIds.end());
+    std::set<int32_t> sinkPortConfigIds(requestedPatch.sinkPortConfigIds.begin(),
+            requestedPatch.sinkPortConfigIds.end());
+    return findOrCreatePatch(sourcePortConfigIds, sinkPortConfigIds, patch, created);
+}
+
+status_t DeviceHalAidl::findOrCreatePatch(
+        const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds,
+        AudioPatch* patch, bool* created) {
+    auto patchIt = findPatch(sourcePortConfigIds, sinkPortConfigIds);
+    if (patchIt == mPatches.end()) {
+        TIME_CHECK();
+        AudioPatch requestedPatch, appliedPatch;
+        requestedPatch.sourcePortConfigIds.insert(requestedPatch.sourcePortConfigIds.end(),
+                sourcePortConfigIds.begin(), sourcePortConfigIds.end());
+        requestedPatch.sinkPortConfigIds.insert(requestedPatch.sinkPortConfigIds.end(),
+                sinkPortConfigIds.begin(), sinkPortConfigIds.end());
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mModule->setAudioPatch(
+                                requestedPatch, &appliedPatch)));
+        patchIt = mPatches.insert(mPatches.end(), std::make_pair(appliedPatch.id, appliedPatch));
+        *created = true;
+    } else {
+        *created = false;
+    }
+    *patch = patchIt->second;
+    return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(const AudioDevice& device,
+        AudioPortConfig* portConfig, bool* created) {
+    auto portConfigIt = findPortConfig(device);
+    if (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());
+            return BAD_VALUE;
+        }
+        AudioPortConfig requestedPortConfig;
+        requestedPortConfig.portId = portsIt->first;
+        RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
+        *created = true;
+    } else {
+        *created = false;
+    }
+    *portConfig = portConfigIt->second;
+    return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(
+        const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle,
+        AudioSource source, AudioPortConfig* portConfig, bool* created) {
+    // These flags get removed one by one in this order when retrying port finding.
+    static const std::vector<AudioInputFlags> kOptionalInputFlags{
+        AudioInputFlags::FAST, AudioInputFlags::RAW };
+    auto portConfigIt = findPortConfig(config, flags, ioHandle);
+    if (portConfigIt == mPortConfigs.end() && flags.has_value()) {
+        auto optionalInputFlagsIt = kOptionalInputFlags.begin();
+        AudioIoFlags matchFlags = flags.value();
+        auto portsIt = findPort(config, matchFlags);
+        while (portsIt == mPorts.end() && matchFlags.getTag() == AudioIoFlags::Tag::input
+                && optionalInputFlagsIt != kOptionalInputFlags.end()) {
+            if (!isBitPositionFlagSet(
+                            matchFlags.get<AudioIoFlags::Tag::input>(), *optionalInputFlagsIt)) {
+                ++optionalInputFlagsIt;
+                continue;
+            }
+            matchFlags.set<AudioIoFlags::Tag::input>(matchFlags.get<AudioIoFlags::Tag::input>() &
+                    ~makeBitPositionFlagMask(*optionalInputFlagsIt++));
+            portsIt = findPort(config, matchFlags);
+            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());
+        }
+        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());
+            return BAD_VALUE;
+        }
+        AudioPortConfig requestedPortConfig;
+        requestedPortConfig.portId = portsIt->first;
+        setPortConfigFromConfig(&requestedPortConfig, config);
+        requestedPortConfig.ext = AudioPortMixExt{ .handle = ioHandle };
+        if (matchFlags.getTag() == AudioIoFlags::Tag::input
+                && source != AudioSource::SYS_RESERVED_INVALID) {
+            requestedPortConfig.ext.get<AudioPortExt::Tag::mix>().usecase =
+                    AudioPortMixExtUseCase::make<AudioPortMixExtUseCase::Tag::source>(source);
+        }
+        RETURN_STATUS_IF_ERROR(createPortConfig(requestedPortConfig, &portConfigIt));
+        *created = true;
+    } else if (!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());
+        return BAD_VALUE;
+    } else {
+        *created = false;
+    }
+    *portConfig = portConfigIt->second;
+    return OK;
+}
+
+status_t DeviceHalAidl::findOrCreatePortConfig(
+        const AudioPortConfig& requestedPortConfig, AudioPortConfig* portConfig, bool* created) {
+    using Tag = AudioPortExt::Tag;
+    if (requestedPortConfig.ext.getTag() == Tag::mix) {
+        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());
+            return BAD_VALUE;
+        }
+        AudioConfig config;
+        setConfigFromPortConfig(&config, requestedPortConfig);
+        AudioSource source = requestedPortConfig.ext.get<Tag::mix>().usecase.getTag() ==
+                AudioPortMixExtUseCase::Tag::source ?
+                requestedPortConfig.ext.get<Tag::mix>().usecase.
+                get<AudioPortMixExtUseCase::Tag::source>() : AudioSource::SYS_RESERVED_INVALID;
+        return findOrCreatePortConfig(config, requestedPortConfig.flags,
+                requestedPortConfig.ext.get<Tag::mix>().handle, source, portConfig, created);
+    } else if (requestedPortConfig.ext.getTag() == Tag::device) {
+        return findOrCreatePortConfig(
+                requestedPortConfig.ext.get<Tag::device>().device, portConfig, created);
+    }
+    ALOGW("%s: unsupported audio port config: %s",
+            __func__, requestedPortConfig.toString().c_str());
+    return BAD_VALUE;
+}
+
+DeviceHalAidl::Patches::iterator DeviceHalAidl::findPatch(
+        const std::set<int32_t>& sourcePortConfigIds, const std::set<int32_t>& sinkPortConfigIds) {
+    return std::find_if(mPatches.begin(), mPatches.end(),
+            [&](const auto& pair) {
+                const auto& p = pair.second;
+                std::set<int32_t> patchSrcs(
+                        p.sourcePortConfigIds.begin(), p.sourcePortConfigIds.end());
+                std::set<int32_t> patchSinks(
+                        p.sinkPortConfigIds.begin(), p.sinkPortConfigIds.end());
+                return sourcePortConfigIds == patchSrcs && sinkPortConfigIds == patchSinks; });
+}
+
+DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(const AudioDevice& device) {
+    if (device.type.type == AudioDeviceType::IN_DEFAULT) {
+        return mPorts.find(mDefaultInputPortId);
+    } else if (device.type.type == AudioDeviceType::OUT_DEFAULT) {
+        return mPorts.find(mDefaultOutputPortId);
+    }
+    return std::find_if(mPorts.begin(), mPorts.end(),
+            [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+}
+
+DeviceHalAidl::Ports::iterator DeviceHalAidl::findPort(
+            const AudioConfig& config, const AudioIoFlags& flags) {
+    auto matcher = [&](const auto& pair) {
+        const auto& p = pair.second;
+        return p.ext.getTag() == AudioPortExt::Tag::mix &&
+                p.flags == flags &&
+                std::find_if(p.profiles.begin(), p.profiles.end(),
+                        [&](const auto& prof) {
+                            return prof.format == config.base.format &&
+                                    std::find(prof.channelMasks.begin(), prof.channelMasks.end(),
+                                            config.base.channelMask) != prof.channelMasks.end() &&
+                                    std::find(prof.sampleRates.begin(), prof.sampleRates.end(),
+                                            config.base.sampleRate) != prof.sampleRates.end();
+                        }) != p.profiles.end(); };
+    return std::find_if(mPorts.begin(), mPorts.end(), matcher);
+}
+
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(const AudioDevice& device) {
+    return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+            [&](const auto& pair) { return audioDeviceMatches(device, pair.second); });
+}
+
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
+            const AudioConfig& config, const std::optional<AudioIoFlags>& flags, int32_t ioHandle) {
+    using Tag = AudioPortExt::Tag;
+    return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+            [&](const auto& pair) {
+                const auto& p = pair.second;
+                LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
+                        !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+                        !p.format.has_value() || !p.flags.has_value(),
+                        "%s: stored mix port config is not fully specified: %s",
+                        __func__, p.toString().c_str());
+                return p.ext.getTag() == Tag::mix &&
+                        isConfigEqualToPortConfig(config, p) &&
+                        (!flags.has_value() || p.flags.value() == flags.value()) &&
+                        p.ext.template get<Tag::mix>().handle == ioHandle; });
+}
+/*
+DeviceHalAidl::PortConfigs::iterator DeviceHalAidl::findPortConfig(
+        const AudioPortConfig& portConfig) {
+    using Tag = AudioPortExt::Tag;
+    if (portConfig.ext.getTag() == Tag::mix) {
+        return std::find_if(mPortConfigs.begin(), mPortConfigs.end(),
+                [&](const auto& pair) {
+                    const auto& p = pair.second;
+                    LOG_ALWAYS_FATAL_IF(p.ext.getTag() == Tag::mix &&
+                            !p.sampleRate.has_value() || !p.channelMask.has_value() ||
+                            !p.format.has_value() || !p.flags.has_value(),
+                            "%s: stored mix port config is not fully specified: %s",
+                            __func__, p.toString().c_str());
+                    return p.ext.getTag() == Tag::mix &&
+                            (!portConfig.sampleRate.has_value() ||
+                                    p.sampleRate == portConfig.sampleRate) &&
+                            (!portConfig.channelMask.has_value() ||
+                                    p.channelMask == portConfig.channelMask) &&
+                            (!portConfig.format.has_value() || p.format == portConfig.format) &&
+                            (!portConfig.flags.has_value() || p.flags == portConfig.flags) &&
+                            p.ext.template get<Tag::mix>().handle ==
+                            portConfig.ext.template get<Tag::mix>().handle; });
+    } else if (portConfig.ext.getTag() == Tag::device) {
+        return findPortConfig(portConfig.ext.get<Tag::device>().device);
+    }
+    return mPortConfigs.end();
+}
+*/
+void DeviceHalAidl::resetPatch(int32_t patchId) {
+    if (auto it = mPatches.find(patchId); it != mPatches.end()) {
+        mPatches.erase(it);
+        TIME_CHECK();
+        if (ndk::ScopedAStatus status = mModule->resetAudioPatch(patchId); !status.isOk()) {
+            ALOGE("%s: error while resetting patch %d: %s",
+                    __func__, patchId, status.getDescription().c_str());
+        }
+        return;
+    }
+    ALOGE("%s: patch id %d not found", __func__, patchId);
+}
+
+void DeviceHalAidl::resetPortConfig(int32_t portConfigId) {
+    if (auto it = mPortConfigs.find(portConfigId); it != mPortConfigs.end()) {
+        mPortConfigs.erase(it);
+        TIME_CHECK();
+        if (ndk::ScopedAStatus status = mModule->resetAudioPortConfig(portConfigId);
+                !status.isOk()) {
+            ALOGE("%s: error while resetting port config %d: %s",
+                    __func__, portConfigId, status.getDescription().c_str());
+        }
+        return;
+    }
+    ALOGE("%s: port config id %d not found", __func__, portConfigId);
+}
+
+void DeviceHalAidl::clearCallbacks(void* cookie) {
+    std::lock_guard l(mLock);
+    mCallbacks.erase(cookie);
+}
+
+sp<StreamOutHalInterfaceCallback> DeviceHalAidl::getStreamOutCallback(void* cookie) {
+    return getCallbackImpl(cookie, &Callbacks::out);
+}
+
+void DeviceHalAidl::setStreamOutCallback(
+        void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) {
+    setCallbackImpl(cookie, &Callbacks::out, cb);
+}
+
+sp<StreamOutHalInterfaceEventCallback> DeviceHalAidl::getStreamOutEventCallback(
+        void* cookie) {
+    return getCallbackImpl(cookie, &Callbacks::event);
+}
+
+void DeviceHalAidl::setStreamOutEventCallback(
+        void* cookie, const sp<StreamOutHalInterfaceEventCallback>& cb) {
+    setCallbackImpl(cookie, &Callbacks::event, cb);
+}
+
+sp<StreamOutHalInterfaceLatencyModeCallback> DeviceHalAidl::getStreamOutLatencyModeCallback(
+        void* cookie) {
+    return getCallbackImpl(cookie, &Callbacks::latency);
+}
+
+void DeviceHalAidl::setStreamOutLatencyModeCallback(
+        void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) {
+    setCallbackImpl(cookie, &Callbacks::latency, cb);
+}
+
+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();
+    }
+    return nullptr;
+}
+template<class C>
+void DeviceHalAidl::setCallbackImpl(
+        void* cookie, wp<C> DeviceHalAidl::Callbacks::* field, const sp<C>& cb) {
+    std::lock_guard l(mLock);
+    if (auto it = mCallbacks.find(cookie); it != mCallbacks.end()) {
+        (it->second).*field = cb;
+    }
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalAidl.h b/media/libaudiohal/impl/DeviceHalAidl.h
new file mode 100644
index 0000000..0a86ddc
--- /dev/null
+++ b/media/libaudiohal/impl/DeviceHalAidl.h
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include <aidl/android/hardware/audio/core/BpModule.h>
+#include <android-base/thread_annotations.h>
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/EffectHalInterface.h>
+
+#include "ConversionHelperAidl.h"
+
+namespace android {
+
+class StreamOutHalInterfaceCallback;
+class StreamOutHalInterfaceEventCallback;
+class StreamOutHalInterfaceLatencyModeCallback;
+
+// The role of the broker is to connect AIDL callback interface implementations
+// with StreamOut callback implementations. Since AIDL requires all callbacks
+// to be provided upfront, while libaudiohal interfaces allow late registration,
+// there is a need to coordinate the matching process.
+class CallbackBroker : public virtual RefBase {
+  public:
+    virtual ~CallbackBroker() = default;
+    // The cookie is always the stream instance pointer. We don't use weak pointers to avoid extra
+    // costs on reference counting. The stream cleans up related entries on destruction. Since
+    // access to the callbacks map is synchronized, the possibility for pointer aliasing due to
+    // allocation of a new stream at the address of previously deleted stream is avoided.
+    virtual void clearCallbacks(void* cookie) = 0;
+    virtual sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) = 0;
+    virtual void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>&) = 0;
+    virtual sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) = 0;
+    virtual void setStreamOutEventCallback(void* cookie,
+            const sp<StreamOutHalInterfaceEventCallback>&) = 0;
+    virtual sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+            void* cookie) = 0;
+    virtual void setStreamOutLatencyModeCallback(
+            void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>&) = 0;
+};
+
+class MicrophoneInfoProvider : public virtual RefBase {
+  public:
+    using Info = std::vector<::aidl::android::media::audio::common::MicrophoneInfo>;
+    virtual ~MicrophoneInfoProvider() = default;
+    // Returns a nullptr if the HAL does not support microphone info retrieval.
+    virtual Info const* getMicrophoneInfo() = 0;
+};
+
+class DeviceHalAidl : public DeviceHalInterface, public ConversionHelperAidl,
+                      public CallbackBroker, public MicrophoneInfoProvider {
+  public:
+    // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
+    status_t getSupportedDevices(uint32_t *devices) override;
+
+    // Check to see if the audio hardware interface has been initialized.
+    status_t initCheck() override;
+
+    // Set the audio volume of a voice call. Range is between 0.0 and 1.0.
+    status_t setVoiceVolume(float volume) override;
+
+    // Set the audio volume for all audio activities other than voice call.
+    status_t setMasterVolume(float volume) override;
+
+    // Get the current master volume value for the HAL.
+    status_t getMasterVolume(float *volume) override;
+
+    // Called when the audio mode changes.
+    status_t setMode(audio_mode_t mode) override;
+
+    // Muting control.
+    status_t setMicMute(bool state) override;
+
+    status_t getMicMute(bool* state) override;
+
+    status_t setMasterMute(bool state) override;
+
+    status_t getMasterMute(bool *state) override;
+
+    // Set global audio parameters.
+    status_t setParameters(const String8& kvPairs) override;
+
+    // Get global audio parameters.
+    status_t getParameters(const String8& keys, String8 *values) override;
+
+    // Returns audio input buffer size according to parameters passed.
+    status_t getInputBufferSize(const struct audio_config* config, size_t* size) override;
+
+    // Creates and opens the audio hardware output stream. The stream is closed
+    // 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;
+
+    // Creates and opens the audio hardware input stream. The stream is closed
+    // by releasing all references to the returned object.
+    status_t openInputStream(audio_io_handle_t handle, audio_devices_t devices,
+                             struct audio_config* config, audio_input_flags_t flags,
+                             const char* address, audio_source_t source,
+                             audio_devices_t outputDevice, const char* outputDeviceAddress,
+                             sp<StreamInHalInterface>* inStream) override;
+
+    // Returns whether createAudioPatch and releaseAudioPatch operations are supported.
+    status_t supportsAudioPatches(bool* supportsPatches) override;
+
+    // Creates an audio patch between several source and sink ports.
+    status_t createAudioPatch(unsigned int num_sources, const struct audio_port_config* sources,
+                              unsigned int num_sinks, const struct audio_port_config* sinks,
+                              audio_patch_handle_t* patch) override;
+
+    // Releases an audio patch.
+    status_t releaseAudioPatch(audio_patch_handle_t patch) override;
+
+    // Fills the list of supported attributes for a given audio port.
+    status_t getAudioPort(struct audio_port* port) override;
+
+    // Fills the list of supported attributes for a given audio port.
+    status_t getAudioPort(struct audio_port_v7 *port) override;
+
+    // Set audio port configuration.
+    status_t setAudioPortConfig(const struct audio_port_config* config) override;
+
+    // List microphones
+    status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones);
+
+    status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+
+    status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
+
+    status_t getMmapPolicyInfos(media::audio::common::AudioMMapPolicyType policyType __unused,
+                                std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos
+                                        __unused) override;
+
+    int32_t getAAudioMixerBurstCount() override;
+
+    int32_t getAAudioHardwareBurstMinUsec() override;
+
+    error::Result<audio_hw_sync_t> getHwAvSync() override;
+
+    status_t dump(int __unused, const Vector<String16>& __unused) override;
+
+    int32_t supportsBluetoothVariableLatency(bool* supports __unused) override;
+
+  private:
+    friend class sp<DeviceHalAidl>;
+
+    struct Callbacks {  // No need to use `atomic_wp` because access is serialized.
+        wp<StreamOutHalInterfaceCallback> out;
+        wp<StreamOutHalInterfaceEventCallback> event;
+        wp<StreamOutHalInterfaceLatencyModeCallback> latency;
+    };
+    struct Microphones {
+        enum Status { UNKNOWN, NOT_SUPPORTED, QUERIED };
+        Status status = Status::UNKNOWN;
+        MicrophoneInfoProvider::Info info;
+    };
+    using Patches = std::map<int32_t /*patch ID*/,
+            ::aidl::android::hardware::audio::core::AudioPatch>;
+    using PortConfigs = std::map<int32_t /*port config ID*/,
+            ::aidl::android::media::audio::common::AudioPortConfig>;
+    using Ports = std::map<int32_t /*port ID*/, ::aidl::android::media::audio::common::AudioPort>;
+    class Cleanups;
+
+    // Must not be constructed directly by clients.
+    DeviceHalAidl(
+            const std::string& instance,
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IModule>& module)
+            : ConversionHelperAidl("DeviceHalAidl"), mInstance(instance), mModule(module) {}
+
+    ~DeviceHalAidl() override = default;
+
+    bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
+            const ::aidl::android::media::audio::common::AudioPort& p);
+    bool audioDeviceMatches(const ::aidl::android::media::audio::common::AudioDevice& device,
+            const ::aidl::android::media::audio::common::AudioPortConfig& p);
+    status_t createPortConfig(
+            const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+            PortConfigs::iterator* result);
+    status_t findOrCreatePatch(
+        const std::set<int32_t>& sourcePortConfigIds,
+        const std::set<int32_t>& sinkPortConfigIds,
+        ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+    status_t findOrCreatePatch(
+        const ::aidl::android::hardware::audio::core::AudioPatch& requestedPatch,
+        ::aidl::android::hardware::audio::core::AudioPatch* patch, bool* created);
+    status_t findOrCreatePortConfig(
+            const ::aidl::android::media::audio::common::AudioDevice& device,
+            ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
+            bool* created);
+    status_t findOrCreatePortConfig(
+            const ::aidl::android::media::audio::common::AudioConfig& config,
+            const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
+            int32_t ioHandle,
+            ::aidl::android::media::audio::common::AudioSource aidlSource,
+            ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+    status_t findOrCreatePortConfig(
+        const ::aidl::android::media::audio::common::AudioPortConfig& requestedPortConfig,
+        ::aidl::android::media::audio::common::AudioPortConfig* portConfig, bool* created);
+    Patches::iterator findPatch(const std::set<int32_t>& sourcePortConfigIds,
+            const std::set<int32_t>& sinkPortConfigIds);
+    Ports::iterator findPort(const ::aidl::android::media::audio::common::AudioDevice& device);
+    Ports::iterator findPort(
+            const ::aidl::android::media::audio::common::AudioConfig& config,
+            const ::aidl::android::media::audio::common::AudioIoFlags& flags);
+    PortConfigs::iterator findPortConfig(
+            const ::aidl::android::media::audio::common::AudioDevice& device);
+    PortConfigs::iterator findPortConfig(
+            const ::aidl::android::media::audio::common::AudioConfig& config,
+            const std::optional<::aidl::android::media::audio::common::AudioIoFlags>& flags,
+            int32_t ioHandle);
+    // Currently unused but may be useful for implementing setAudioPortConfig
+    // PortConfigs::iterator findPortConfig(
+    //         const ::aidl::android::media::audio::common::AudioPortConfig& portConfig);
+    status_t prepareToOpenStream(
+        int32_t aidlHandle,
+        const ::aidl::android::media::audio::common::AudioDevice& aidlDevice,
+        const ::aidl::android::media::audio::common::AudioIoFlags& aidlFlags,
+        ::aidl::android::media::audio::common::AudioSource aidlSource,
+        struct audio_config* config,
+        Cleanups* cleanups,
+        ::aidl::android::media::audio::common::AudioConfig* aidlConfig,
+        ::aidl::android::media::audio::common::AudioPortConfig* mixPortConfig,
+        int32_t* nominalLatency);
+    void resetPatch(int32_t patchId);
+    void resetPortConfig(int32_t portConfigId);
+
+    // CallbackBroker implementation
+    void clearCallbacks(void* cookie) override;
+    sp<StreamOutHalInterfaceCallback> getStreamOutCallback(void* cookie) override;
+    void setStreamOutCallback(void* cookie, const sp<StreamOutHalInterfaceCallback>& cb) override;
+    sp<StreamOutHalInterfaceEventCallback> getStreamOutEventCallback(void* cookie) override;
+    void setStreamOutEventCallback(void* cookie,
+            const sp<StreamOutHalInterfaceEventCallback>& cb) override;
+    sp<StreamOutHalInterfaceLatencyModeCallback> getStreamOutLatencyModeCallback(
+            void* cookie) override;
+    void setStreamOutLatencyModeCallback(
+            void* cookie, const sp<StreamOutHalInterfaceLatencyModeCallback>& cb) override;
+    // Implementation helpers.
+    template<class C> sp<C> getCallbackImpl(void* cookie, wp<C> Callbacks::* field);
+    template<class C> void setCallbackImpl(void* cookie, wp<C> Callbacks::* field, const sp<C>& cb);
+
+    // MicrophoneInfoProvider implementation
+    MicrophoneInfoProvider::Info const* getMicrophoneInfo() override;
+
+    const std::string mInstance;
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IModule> mModule;
+    Ports mPorts;
+    int32_t mDefaultInputPortId = -1;
+    int32_t mDefaultOutputPortId = -1;
+    PortConfigs mPortConfigs;
+    Patches mPatches;
+    Microphones mMicrophones;
+    std::mutex mLock;
+    std::map<void*, Callbacks> mCallbacks GUARDED_BY(mLock);
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index 0cdf621..12acebd 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -46,9 +46,6 @@
 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 
-#define TIME_CHECK() auto timeCheck = \
-        mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
-
 DeviceHalHidl::DeviceHalHidl(const sp<::android::hardware::audio::CPP_VERSION::IDevice>& device)
         : CoreConversionHelperHidl("DeviceHalHidl"), mDevice(device) {
 }
@@ -459,12 +456,13 @@
 
 #if MAJOR_VERSION == 2
 status_t DeviceHalHidl::getMicrophones(
-        std::vector<media::MicrophoneInfo> *microphonesInfo __unused) {
+        std::vector<audio_microphone_characteristic_t> *microphonesInfo __unused) {
     if (mDevice == 0) return NO_INIT;
     return INVALID_OPERATION;
 }
 #elif MAJOR_VERSION >= 4
-status_t DeviceHalHidl::getMicrophones(std::vector<media::MicrophoneInfo> *microphonesInfo) {
+status_t DeviceHalHidl::getMicrophones(
+        std::vector<audio_microphone_characteristic_t> *microphonesInfo) {
     TIME_CHECK();
     if (mDevice == 0) return NO_INIT;
     Result retval;
@@ -475,8 +473,7 @@
             audio_microphone_characteristic_t dst;
             //convert
             (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
-            media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
-            microphonesInfo->push_back(microphone);
+            microphonesInfo->push_back(dst);
         }
     });
     return processReturn("getMicrophones", ret, retval);
diff --git a/media/libaudiohal/impl/DeviceHalHidl.h b/media/libaudiohal/impl/DeviceHalHidl.h
index f6519b6..052eb65 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.h
+++ b/media/libaudiohal/impl/DeviceHalHidl.h
@@ -30,87 +30,74 @@
 {
   public:
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
-    virtual status_t getSupportedDevices(uint32_t *devices);
+    status_t getSupportedDevices(uint32_t *devices) override;
 
     // Check to see if the audio hardware interface has been initialized.
-    virtual status_t initCheck();
+    status_t initCheck() override;
 
     // Set the audio volume of a voice call. Range is between 0.0 and 1.0.
-    virtual status_t setVoiceVolume(float volume);
+    status_t setVoiceVolume(float volume) override;
 
     // Set the audio volume for all audio activities other than voice call.
-    virtual status_t setMasterVolume(float volume);
+    status_t setMasterVolume(float volume) override;
 
     // Get the current master volume value for the HAL.
-    virtual status_t getMasterVolume(float *volume);
+    status_t getMasterVolume(float *volume) override;
 
     // Called when the audio mode changes.
-    virtual status_t setMode(audio_mode_t mode);
+    status_t setMode(audio_mode_t mode) override;
 
     // Muting control.
-    virtual status_t setMicMute(bool state);
-    virtual status_t getMicMute(bool *state);
-    virtual status_t setMasterMute(bool state);
-    virtual status_t getMasterMute(bool *state);
+    status_t setMicMute(bool state) override;
+    status_t getMicMute(bool *state) override;
+    status_t setMasterMute(bool state) override;
+    status_t getMasterMute(bool *state) override;
 
     // Set global audio parameters.
-    virtual status_t setParameters(const String8& kvPairs);
+    status_t setParameters(const String8& kvPairs) override;
 
     // Get global audio parameters.
-    virtual status_t getParameters(const String8& keys, String8 *values);
+    status_t getParameters(const String8& keys, String8 *values) override;
 
     // Returns audio input buffer size according to parameters passed.
-    virtual status_t getInputBufferSize(const struct audio_config *config,
-            size_t *size);
+    status_t getInputBufferSize(const struct audio_config* config, size_t* size) override;
 
     // Creates and opens the audio hardware output stream. The stream is closed
     // by releasing all references to the returned object.
-    virtual 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);
+    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;
 
     // Creates and opens the audio hardware input stream. The stream is closed
     // by releasing all references to the returned object.
-    virtual status_t openInputStream(
-            audio_io_handle_t handle,
-            audio_devices_t devices,
-            struct audio_config *config,
-            audio_input_flags_t flags,
-            const char *address,
-            audio_source_t source,
-            audio_devices_t outputDevice,
-            const char *outputDeviceAddress,
-            sp<StreamInHalInterface> *inStream);
+    status_t openInputStream(audio_io_handle_t handle, audio_devices_t devices,
+                             struct audio_config* config, audio_input_flags_t flags,
+                             const char* address, audio_source_t source,
+                             audio_devices_t outputDevice, const char* outputDeviceAddress,
+                             sp<StreamInHalInterface>* inStream) override;
 
     // Returns whether createAudioPatch and releaseAudioPatch operations are supported.
-    virtual status_t supportsAudioPatches(bool *supportsPatches);
+    status_t supportsAudioPatches(bool* supportsPatches) override;
 
     // Creates an audio patch between several source and sink ports.
-    virtual status_t createAudioPatch(
-            unsigned int num_sources,
-            const struct audio_port_config *sources,
-            unsigned int num_sinks,
-            const struct audio_port_config *sinks,
-            audio_patch_handle_t *patch);
+    status_t createAudioPatch(unsigned int num_sources, const struct audio_port_config* sources,
+                              unsigned int num_sinks, const struct audio_port_config* sinks,
+                              audio_patch_handle_t* patch) override;
 
     // Releases an audio patch.
-    virtual status_t releaseAudioPatch(audio_patch_handle_t patch);
+    status_t releaseAudioPatch(audio_patch_handle_t patch) override;
 
     // Fills the list of supported attributes for a given audio port.
-    virtual status_t getAudioPort(struct audio_port *port);
+    status_t getAudioPort(struct audio_port *port) override;
 
     // Fills the list of supported attributes for a given audio port.
-    virtual status_t getAudioPort(struct audio_port_v7 *port);
+    status_t getAudioPort(struct audio_port_v7 *port) override;
 
     // Set audio port configuration.
-    virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+    status_t setAudioPortConfig(const struct audio_port_config *config) override;
 
     // List microphones
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+    status_t getMicrophones(std::vector<audio_microphone_characteristic_t>* microphones) override;
 
     status_t addDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
     status_t removeDeviceEffect(audio_port_handle_t device, sp<EffectHalInterface> effect) override;
@@ -132,6 +119,11 @@
         return INVALID_OPERATION;
     }
 
+    int32_t supportsBluetoothVariableLatency(bool* supports __unused) override {
+        // TODO: Implement the HAL query when moving to AIDL HAL.
+        return INVALID_OPERATION;
+    }
+
     status_t setConnectedState(const struct audio_port_v7 *port, bool connected) override;
 
     error::Result<audio_hw_sync_t> getHwAvSync() override;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
new file mode 100644
index 0000000..2eaaf5d
--- /dev/null
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DevicesFactoryHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/core/IModule.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <memory>
+#include <utils/Log.h>
+
+#include "DeviceHalAidl.h"
+#include "DevicesFactoryHalAidl.h"
+
+using namespace ::aidl::android::hardware::audio::core;
+using ::android::detail::AudioHalVersionInfo;
+
+namespace android {
+
+DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> iconfig)
+    : mIConfig(std::move(iconfig)) {
+    ALOG_ASSERT(iconfig != nullptr, "Provided default IConfig service is NULL");
+}
+
+// Opens a device with the specified name. To close the device, it is
+// necessary to release references to the returned object.
+status_t DevicesFactoryHalAidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
+    if (name == nullptr || device == nullptr) {
+        return BAD_VALUE;
+    }
+
+    std::shared_ptr<IModule> service;
+    // FIXME: Normally we will list available HAL modules and connect to them,
+    // however currently we still get the list of module names from the config.
+    // Since the example service does not have all modules, the SM will wait
+    // for the missing ones forever.
+    if (strcmp(name, "primary") == 0 || strcmp(name, "r_submix") == 0 || strcmp(name, "usb") == 0) {
+        if (strcmp(name, "primary") == 0) name = "default";
+        auto serviceName = std::string(IModule::descriptor) + "/" + name;
+        service = IModule::fromBinder(
+                ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+        ALOGE_IF(service == nullptr, "%s fromBinder %s failed", __func__, serviceName.c_str());
+    }
+    // If the service is a nullptr, the device will not be really functional,
+    // but will not crash either.
+    *device = sp<DeviceHalAidl>::make(name, service);
+    return OK;
+}
+
+status_t DevicesFactoryHalAidl::getHalPids(std::vector<pid_t> *pids) {
+    if (pids == nullptr) {
+        return BAD_VALUE;
+    }
+    // The functionality for retrieving debug infos of services is not exposed via the NDK.
+    sp<IServiceManager> sm = defaultServiceManager();
+    if (sm == nullptr) {
+        return NO_INIT;
+    }
+    std::set<pid_t> pidsSet;
+    const auto moduleServiceName = std::string(IModule::descriptor) + "/";
+    auto debugInfos = sm->getServiceDebugInfo();
+    for (const auto& info : debugInfos) {
+        if (info.pid > 0 &&
+                info.name.size() > moduleServiceName.size() && // '>' as there must be instance name
+                info.name.substr(0, moduleServiceName.size()) == moduleServiceName) {
+            pidsSet.insert(info.pid);
+        }
+    }
+    *pids = {pidsSet.begin(), pidsSet.end()};
+    return NO_ERROR;
+}
+
+status_t DevicesFactoryHalAidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+    // Dynamic registration of module instances is not supported. The functionality
+    // in the audio server which is related to this callback can be removed together
+    // with HIDL support.
+    ALOG_ASSERT(callback != nullptr);
+    if (callback != nullptr) {
+        callback->onNewDevicesAvailable();
+    }
+    return NO_ERROR;
+}
+
+AudioHalVersionInfo DevicesFactoryHalAidl::getHalVersion() const {
+    int32_t versionNumber = 0;
+    if (mIConfig != 0) {
+        if (ndk::ScopedAStatus status = mIConfig->getInterfaceVersion(&versionNumber);
+                !status.isOk()) {
+            ALOGE("%s getInterfaceVersion failed: %s", __func__, status.getDescription().c_str());
+        }
+    } else {
+        ALOGW("%s no IConfig instance", __func__);
+    }
+    // AIDL does not have minor version, fill 0 for all versions
+    return AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, versionNumber);
+}
+
+// Main entry-point to the shared library.
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
+    auto serviceName = std::string(IConfig::descriptor) + "/default";
+    auto service = IConfig::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+    if (!service) {
+        ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
+        return nullptr;
+    }
+    return new DevicesFactoryHalAidl(service);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalAidl.h b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
new file mode 100644
index 0000000..cb627bc
--- /dev/null
+++ b/media/libaudiohal/impl/DevicesFactoryHalAidl.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/IConfig.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+class DevicesFactoryHalAidl : public DevicesFactoryHalInterface
+{
+  public:
+    explicit DevicesFactoryHalAidl(
+            std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> iConfig);
+
+    // Opens a device with the specified name. To close the device, it is
+    // necessary to release references to the returned object.
+    status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
+
+    status_t getHalPids(std::vector<pid_t> *pids) override;
+
+    status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
+
+    android::detail::AudioHalVersionInfo getHalVersion() const override;
+
+  private:
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mIConfig;
+    ~DevicesFactoryHalAidl() = default;
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp b/media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
similarity index 74%
copy from media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
copy to media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
index 2c6f2c6..5bf6d89 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalEntry.cpp
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-extern "C" void* createIEffectsFactoryImpl();
+#include "android/media/AudioHalVersion.h"
 
-extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
-    return createIEffectsFactoryImpl();
+extern "C" void* createIDevicesFactoryImpl();
+
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+    return createIDevicesFactoryImpl();
 }
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index 4069a6b..9f06f83 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -29,6 +29,7 @@
 #include "DeviceHalHidl.h"
 #include "DevicesFactoryHalHidl.h"
 
+using ::android::detail::AudioHalVersionInfo;
 using ::android::hardware::audio::CPP_VERSION::IDevice;
 using ::android::hardware::audio::CORE_TYPES_CPP_VERSION::Result;
 using ::android::hardware::Return;
@@ -226,8 +227,13 @@
     return mDeviceFactories;
 }
 
+
+AudioHalVersionInfo DevicesFactoryHalHidl::getHalVersion() const {
+    return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
+}
+
 // Main entry-point to the shared library.
-extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
+extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
     auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
     return service ? new DevicesFactoryHalHidl(service) : nullptr;
 }
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index ffd229d..5294728 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -45,7 +45,7 @@
 
     status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
 
-    float getHalVersion() const override { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+    android::detail::AudioHalVersionInfo getHalVersion() const override;
 
   private:
     friend class ServiceNotificationListener;
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.cpp b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
new file mode 100644
index 0000000..a701852
--- /dev/null
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <cstdint>
+#include <cstring>
+#include <sys/mman.h>
+#define LOG_TAG "EffectBufferHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <cutils/ashmem.h>
+#include <utils/Log.h>
+
+#include "EffectBufferHalAidl.h"
+
+using ndk::ScopedFileDescriptor;
+
+namespace android {
+namespace effect {
+
+// static
+status_t EffectBufferHalAidl::allocate(size_t size, sp<EffectBufferHalInterface>* buffer) {
+    return mirror(nullptr, size, buffer);
+}
+
+status_t EffectBufferHalAidl::mirror(void* external, size_t size,
+                                     sp<EffectBufferHalInterface>* buffer) {
+    sp<EffectBufferHalAidl> tempBuffer = new EffectBufferHalAidl(size);
+    status_t status = tempBuffer.get()->init();
+    if (status != OK) {
+        ALOGE("%s init failed %d", __func__, status);
+        return status;
+    }
+
+    tempBuffer->setExternalData(external);
+    *buffer = tempBuffer;
+    return OK;
+}
+
+EffectBufferHalAidl::EffectBufferHalAidl(size_t size)
+    : mBufferSize(size),
+      mFrameCountChanged(false),
+      mExternalData(nullptr),
+      mAudioBuffer{0, {nullptr}} {
+}
+
+EffectBufferHalAidl::~EffectBufferHalAidl() {
+}
+
+status_t EffectBufferHalAidl::init() {
+    int fd = ashmem_create_region("audioEffectAidl", mBufferSize);
+    if (fd < 0) {
+        ALOGE("%s create ashmem failed %d", __func__, fd);
+        return fd;
+    }
+
+    ScopedFileDescriptor tempFd(fd);
+    mAudioBuffer.raw = mmap(nullptr /* address */, mBufferSize /* length */, PROT_READ | PROT_WRITE,
+                            MAP_SHARED, fd, 0 /* offset */);
+    if (mAudioBuffer.raw == MAP_FAILED) {
+        ALOGE("mmap failed for fd %d", fd);
+        mAudioBuffer.raw = nullptr;
+        return INVALID_OPERATION;
+    }
+
+    mMemory = {std::move(tempFd), static_cast<int64_t>(mBufferSize)};
+    return OK;
+}
+
+audio_buffer_t* EffectBufferHalAidl::audioBuffer() {
+    return &mAudioBuffer;
+}
+
+void* EffectBufferHalAidl::externalData() const {
+    return mExternalData;
+}
+
+void EffectBufferHalAidl::setFrameCount(size_t frameCount) {
+    mAudioBuffer.frameCount = frameCount;
+    mFrameCountChanged = true;
+}
+
+bool EffectBufferHalAidl::checkFrameCountChange() {
+    bool result = mFrameCountChanged;
+    mFrameCountChanged = false;
+    return result;
+}
+
+void EffectBufferHalAidl::setExternalData(void* external) {
+    mExternalData = external;
+}
+
+void EffectBufferHalAidl::update() {
+    update(mBufferSize);
+}
+
+void EffectBufferHalAidl::commit() {
+    commit(mBufferSize);
+}
+
+void EffectBufferHalAidl::copy(void* dst, const void* src, size_t n) const {
+    if (!dst || !src) {
+        return;
+    }
+    std::memcpy(dst, src, std::min(n, mBufferSize));
+}
+
+void EffectBufferHalAidl::update(size_t n) {
+    copy(mAudioBuffer.raw, mExternalData, n);
+}
+
+void EffectBufferHalAidl::commit(size_t n) {
+    copy(mExternalData, mAudioBuffer.raw, n);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectBufferHalAidl.h b/media/libaudiohal/impl/EffectBufferHalAidl.h
new file mode 100644
index 0000000..035314b
--- /dev/null
+++ b/media/libaudiohal/impl/EffectBufferHalAidl.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/common/Ashmem.h>
+
+#include <media/audiohal/EffectBufferHalInterface.h>
+#include <system/audio_effect.h>
+
+namespace android {
+namespace effect {
+
+class EffectBufferHalAidl : public EffectBufferHalInterface {
+  public:
+    static status_t allocate(size_t size, sp<EffectBufferHalInterface>* buffer);
+    static status_t mirror(void* external, size_t size, sp<EffectBufferHalInterface>* buffer);
+
+    audio_buffer_t* audioBuffer() override;
+    void* externalData() const override;
+
+    size_t getSize() const override { return mBufferSize; }
+
+    void setExternalData(void* external) override;
+    void setFrameCount(size_t frameCount) override;
+    bool checkFrameCountChange() override;
+
+    void update() override;
+    void commit() override;
+    void update(size_t size) override;
+    void commit(size_t size) override;
+
+  private:
+    friend class EffectBufferHalInterface;
+
+    // buffer size in bytes
+    const size_t mBufferSize;
+    bool mFrameCountChanged;
+    void* mExternalData;
+    aidl::android::hardware::common::Ashmem mMemory;
+    audio_buffer_t mAudioBuffer;
+
+    // Can not be constructed directly by clients.
+    explicit EffectBufferHalAidl(size_t size);
+
+    ~EffectBufferHalAidl();
+    void copy(void* dst, const void* src, size_t n) const;
+    status_t init();
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
new file mode 100644
index 0000000..519b871
--- /dev/null
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "EffectConversionHelperAidl"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include <utils/Log.h>
+
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::CommandId;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::Flags;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioMode;
+using ::aidl::android::media::audio::common::AudioSource;
+using android::effect::utils::EffectParamReader;
+using android::effect::utils::EffectParamWriter;
+
+using ::android::status_t;
+
+const std::map<uint32_t /* effect_command_e */, EffectConversionHelperAidl::CommandHandler>
+        EffectConversionHelperAidl::mCommandHandlerMap = {
+                {EFFECT_CMD_INIT, &EffectConversionHelperAidl::handleInit},
+                {EFFECT_CMD_SET_PARAM, &EffectConversionHelperAidl::handleSetParameter},
+                {EFFECT_CMD_GET_PARAM, &EffectConversionHelperAidl::handleGetParameter},
+                {EFFECT_CMD_SET_CONFIG, &EffectConversionHelperAidl::handleSetConfig},
+                {EFFECT_CMD_GET_CONFIG, &EffectConversionHelperAidl::handleGetConfig},
+                {EFFECT_CMD_RESET, &EffectConversionHelperAidl::handleReset},
+                {EFFECT_CMD_ENABLE, &EffectConversionHelperAidl::handleEnable},
+                {EFFECT_CMD_DISABLE, &EffectConversionHelperAidl::handleDisable},
+                {EFFECT_CMD_SET_AUDIO_SOURCE, &EffectConversionHelperAidl::handleSetAudioSource},
+                {EFFECT_CMD_SET_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
+                {EFFECT_CMD_SET_INPUT_DEVICE, &EffectConversionHelperAidl::handleSetDevice},
+                {EFFECT_CMD_SET_VOLUME, &EffectConversionHelperAidl::handleSetVolume},
+                {EFFECT_CMD_OFFLOAD, &EffectConversionHelperAidl::handleSetOffload},
+                // Only visualizer support these commands, reuse of EFFECT_CMD_FIRST_PROPRIETARY
+                {VISUALIZER_CMD_CAPTURE, &EffectConversionHelperAidl::handleVisualizerCapture},
+                {VISUALIZER_CMD_MEASURE, &EffectConversionHelperAidl::handleVisualizerMeasure}};
+
+EffectConversionHelperAidl::EffectConversionHelperAidl(
+        std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+        int32_t sessionId, int32_t ioId, const Descriptor& desc)
+    : mSessionId(sessionId),
+      mIoId(ioId),
+      mDesc(desc),
+      mEffect(std::move(effect)),
+      mIsInputStream(mDesc.common.flags.type == Flags::Type::PRE_PROC) {
+    mCommon.session = sessionId;
+    mCommon.ioHandle = ioId;
+    mCommon.input = mCommon.output = kDefaultAudioConfig;
+}
+
+status_t EffectConversionHelperAidl::handleCommand(uint32_t cmdCode, uint32_t cmdSize,
+                                                   void* pCmdData, uint32_t* replySize,
+                                                   void* pReplyData) {
+    const auto& handler = mCommandHandlerMap.find(cmdCode);
+    if (handler == mCommandHandlerMap.end() || !handler->second) {
+        ALOGE("%s handler for command %u doesn't exist", __func__, cmdCode);
+        return BAD_VALUE;
+    }
+    return (this->*handler->second)(cmdSize, pCmdData, replySize, pReplyData);
+}
+
+status_t EffectConversionHelperAidl::handleInit(uint32_t cmdSize __unused,
+                                                const void* pCmdData __unused, uint32_t* replySize,
+                                                void* pReplyData) {
+    if (!replySize || *replySize < sizeof(int) || !pReplyData) {
+        return BAD_VALUE;
+    }
+
+    return *(status_t*)pReplyData =
+                   statusTFromBinderStatus(mEffect->open(mCommon, std::nullopt, &mOpenReturn));
+}
+
+status_t EffectConversionHelperAidl::handleSetParameter(uint32_t cmdSize, const void* pCmdData,
+                                                        uint32_t* replySize, void* pReplyData) {
+    if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize ||
+        *replySize < sizeof(int) || !pReplyData) {
+        return BAD_VALUE;
+    }
+
+    auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
+    if (!reader.validateCmdSize(cmdSize)) {
+        ALOGE("%s illegal param %s size %u", __func__, reader.toString().c_str(), cmdSize);
+        return BAD_VALUE;
+    }
+
+    status_t ret = setParameter(reader);
+    EffectParamWriter writer(*(effect_param_t*)pReplyData);
+    writer.setStatus(ret);
+    return *(status_t*)pReplyData = ret;
+}
+
+status_t EffectConversionHelperAidl::handleGetParameter(uint32_t cmdSize, const void* pCmdData,
+                                                        uint32_t* replySize, void* pReplyData) {
+    if (cmdSize < sizeof(effect_param_t) || !pCmdData || !replySize || !pReplyData) {
+        return BAD_VALUE;
+    }
+
+    const auto reader = EffectParamReader(*(effect_param_t*)pCmdData);
+    if (*replySize < sizeof(effect_param_t) + reader.getParameterSize()) {
+        ALOGE("%s illegal param %s, replySize %u", __func__, reader.toString().c_str(), *replySize);
+        return BAD_VALUE;
+    }
+
+    // copy effect_param_t and parameters
+    memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + reader.getParameterSize());
+    auto writer = EffectParamWriter(*(effect_param_t*)pReplyData);
+    status_t ret = getParameter(writer);
+    writer.finishValueWrite();
+    writer.setStatus(ret);
+    *replySize = writer.getTotalSize();
+    if (ret != OK) {
+        ALOGE("%s error ret %d, %s", __func__, ret, writer.toString().c_str());
+    }
+    return ret;
+}
+
+status_t EffectConversionHelperAidl::handleSetConfig(uint32_t cmdSize, const void* pCmdData,
+                                                     uint32_t* replySize, void* pReplyData) {
+    if (!replySize || *replySize != sizeof(int) || !pReplyData ||
+        cmdSize != sizeof(effect_config_t)) {
+        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+              pReplyData);
+        return BAD_VALUE;
+    }
+
+    effect_config_t* config = (effect_config_t*)pCmdData;
+    Parameter::Common aidlCommon = {
+            .session = mSessionId,
+            .ioHandle = mIoId,
+            .input = {.base = VALUE_OR_RETURN_STATUS(
+                              ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
+                                      config->inputCfg, mIsInputStream))},
+            .output = {.base = VALUE_OR_RETURN_STATUS(
+                               ::aidl::android::legacy2aidl_buffer_config_t_AudioConfigBase(
+                                       config->outputCfg, mIsInputStream))}};
+
+    Parameter aidlParam = UNION_MAKE(Parameter, common, aidlCommon);
+
+    status_t ret = statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+    EffectParamWriter writer(*(effect_param_t*)pReplyData);
+    writer.setStatus(ret);
+    return ret;
+}
+
+status_t EffectConversionHelperAidl::handleGetConfig(uint32_t cmdSize __unused,
+                                                     const void* pCmdData __unused,
+                                                     uint32_t* replySize, void* pReplyData) {
+    if (!replySize || *replySize != sizeof(effect_config_t) || !pReplyData) {
+        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    Parameter param;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(
+            Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common), &param)));
+
+    const auto& common = param.get<Parameter::common>();
+    effect_config_t* pConfig = (effect_config_t*)pReplyData;
+    pConfig->inputCfg = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(common.input.base, true));
+    pConfig->outputCfg =
+            VALUE_OR_RETURN_STATUS(::aidl::android::aidl2legacy_AudioConfigBase_buffer_config_t(
+                    common.output.base, false));
+    mCommon = common;
+    return OK;
+}
+
+status_t EffectConversionHelperAidl::handleReset(uint32_t cmdSize __unused,
+                                                 const void* pCmdData __unused, uint32_t* replySize,
+                                                 void* pReplyData) {
+    if (!replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    return statusTFromBinderStatus(mEffect->command(CommandId::RESET));
+}
+
+status_t EffectConversionHelperAidl::handleEnable(uint32_t cmdSize __unused,
+                                                  const void* pCmdData __unused,
+                                                  uint32_t* replySize, void* pReplyData) {
+    if (!replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    return statusTFromBinderStatus(mEffect->command(CommandId::START));
+}
+
+status_t EffectConversionHelperAidl::handleDisable(uint32_t cmdSize __unused,
+                                                   const void* pCmdData __unused,
+                                                   uint32_t* replySize, void* pReplyData) {
+    if (!replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    return statusTFromBinderStatus(mEffect->command(CommandId::STOP));
+}
+
+status_t EffectConversionHelperAidl::handleSetAudioSource(uint32_t cmdSize, const void* pCmdData,
+                                                          uint32_t* replySize, void* pReplyData) {
+    if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+              pReplyData);
+        return BAD_VALUE;
+    }
+
+    audio_source_t source = *(audio_source_t*)pCmdData;
+    AudioSource aidlSource =
+            VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_source_t_AudioSource(source));
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mEffect->setParameter(Parameter::make<Parameter::source>(aidlSource))));
+    return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetAudioMode(uint32_t cmdSize, const void* pCmdData,
+                                                        uint32_t* replySize, void* pReplyData) {
+    if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+              pReplyData);
+        return BAD_VALUE;
+    }
+    audio_mode_t mode = *(audio_mode_t *)pCmdData;
+    AudioMode aidlMode =
+            VALUE_OR_RETURN_STATUS(::aidl::android::legacy2aidl_audio_mode_t_AudioMode(mode));
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mEffect->setParameter(Parameter::make<Parameter::mode>(aidlMode))));
+    return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetDevice(uint32_t cmdSize, const void* pCmdData,
+                                                     uint32_t* replySize, void* pReplyData) {
+    if (cmdSize != sizeof(uint32_t) || !pCmdData || !replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+              pReplyData);
+        return BAD_VALUE;
+    }
+    // TODO: convert from audio_devices_t to std::vector<AudioDeviceDescription>
+    // const auto& legacyDevice = *(uint32_t*)(pCmdData);
+    std::vector<AudioDeviceDescription> aidlDevices;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mEffect->setParameter(Parameter::make<Parameter::deviceDescription>(aidlDevices))));
+    return *static_cast<int32_t*>(pReplyData) = OK;
+}
+status_t EffectConversionHelperAidl::handleSetVolume(uint32_t cmdSize, const void* pCmdData,
+                                                     uint32_t* replySize __unused,
+                                                     void* pReplyData __unused) {
+    if (cmdSize != 2 * sizeof(uint32_t) || !pCmdData) {
+        ALOGE("%s parameter invalid %u %p", __func__, cmdSize, pCmdData);
+        return BAD_VALUE;
+    }
+    Parameter::VolumeStereo volume = {.left = (float)(*(uint32_t*)pCmdData) / (1 << 24),
+                                      .right = (float)(*(uint32_t*)pCmdData + 1) / (1 << 24)};
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
+            mEffect->setParameter(Parameter::make<Parameter::volumeStereo>(volume))));
+    return OK;
+}
+
+status_t EffectConversionHelperAidl::handleSetOffload(uint32_t cmdSize, const void* pCmdData,
+                                                      uint32_t* replySize, void* pReplyData) {
+    if (cmdSize < sizeof(effect_offload_param_t) || !pCmdData || !replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %u %p %p %p", __func__, cmdSize, pCmdData, replySize,
+              pReplyData);
+        return BAD_VALUE;
+    }
+    // TODO: handle this after effectproxy implemented in libaudiohal
+    return *static_cast<int32_t*>(pReplyData) = OK;
+}
+
+status_t EffectConversionHelperAidl::handleVisualizerCapture(uint32_t cmdSize __unused,
+                                                             const void* pCmdData __unused,
+                                                             uint32_t* replySize,
+                                                             void* pReplyData) {
+    if (!replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    const auto& uuid = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+    if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+        ALOGE("%s visualizer command not supported by %s", __func__,
+              mDesc.common.id.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    return visualizerCapture(replySize, pReplyData);
+}
+
+status_t EffectConversionHelperAidl::handleVisualizerMeasure(uint32_t cmdSize __unused,
+                                                             const void* pCmdData __unused,
+                                                             uint32_t* replySize,
+                                                             void* pReplyData) {
+    if (!replySize || !pReplyData) {
+        ALOGE("%s parameter invalid %p %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    const auto& uuid = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_AudioUuid_audio_uuid_t(mDesc.common.id.type));
+    if (0 != memcmp(&uuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t))) {
+        ALOGE("%s visualizer command not supported by %s", __func__,
+              mDesc.common.id.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    return visualizerMeasure(replySize, pReplyData);
+}
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
new file mode 100644
index 0000000..54df1b8
--- /dev/null
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/Errors.h>
+
+#include <aidl/android/hardware/audio/effect/BpEffect.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/audio_effects_utils.h>
+
+namespace android {
+namespace effect {
+
+class EffectConversionHelperAidl {
+  public:
+    status_t handleCommand(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
+                           void* pReplyData);
+    virtual ~EffectConversionHelperAidl() {}
+    const ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn&
+    getEffectReturnParam() const {
+        return mOpenReturn;
+    }
+
+  protected:
+    const int32_t mSessionId;
+    const int32_t mIoId;
+    const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+    const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
+    // whether the effect is instantiated on an input stream
+    const bool mIsInputStream;
+    ::aidl::android::hardware::audio::effect::IEffect::OpenEffectReturn mOpenReturn;
+    ::aidl::android::hardware::audio::effect::Parameter::Common mCommon;
+
+    EffectConversionHelperAidl(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+
+    status_t handleSetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                                void* pReplyData);
+    status_t handleGetParameter(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                                void* pReplyData);
+
+  private:
+    const aidl::android::media::audio::common::AudioFormatDescription kDefaultFormatDescription = {
+            .type = aidl::android::media::audio::common::AudioFormatType::PCM,
+            .pcm = aidl::android::media::audio::common::PcmType::FLOAT_32_BIT};
+
+    static constexpr int kDefaultframeCount = 0x100;
+
+    using AudioChannelLayout = aidl::android::media::audio::common::AudioChannelLayout;
+    const aidl::android::media::audio::common::AudioConfig kDefaultAudioConfig = {
+            .base = {.sampleRate = 44100,
+                     .channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+                             AudioChannelLayout::LAYOUT_STEREO),
+                     .format = kDefaultFormatDescription},
+            .frameCount = kDefaultframeCount};
+    // command handler map
+    typedef status_t (EffectConversionHelperAidl::*CommandHandler)(uint32_t /* cmdSize */,
+                                                                   const void* /* pCmdData */,
+                                                                   uint32_t* /* replySize */,
+                                                                   void* /* pReplyData */);
+    static const std::map<uint32_t /* effect_command_e */, CommandHandler> mCommandHandlerMap;
+
+    status_t handleInit(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                        void* pReplyData);
+    status_t handleSetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                             void* pReplyData);
+    status_t handleGetConfig(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                             void* pReplyData);
+    status_t handleEnable(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                          void* pReplyData);
+    status_t handleDisable(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                           void* pReplyData);
+    status_t handleReset(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                         void* pReplyData);
+    status_t handleSetAudioSource(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                                  void* pReplyData);
+    status_t handleSetAudioMode(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                                void* pReplyData);
+    status_t handleSetDevice(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                             void* pReplyData);
+    status_t handleSetVolume(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                             void* pReplyData);
+    status_t handleSetOffload(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                              void* pReplyData);
+    status_t handleVisualizerCapture(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                                     void* pReplyData);
+    status_t handleVisualizerMeasure(uint32_t cmdSize, const void* pCmdData, uint32_t* replySize,
+                                     void* pReplyData);
+
+    // implemented by conversion of each effect
+    virtual status_t setParameter(utils::EffectParamReader& param) = 0;
+    virtual status_t getParameter(utils::EffectParamWriter& param) = 0;
+    virtual status_t visualizerCapture(uint32_t* replySize __unused, void* pReplyData __unused) {
+        return BAD_VALUE;
+    }
+    virtual status_t visualizerMeasure(uint32_t* replySize __unused, void* pReplyData __unused) {
+        return BAD_VALUE;
+    }
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
new file mode 100644
index 0000000..0c19ac8
--- /dev/null
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+#define LOG_TAG "EffectHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <memory>
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <media/AidlConversionUtil.h>
+#include <media/EffectsFactoryApi.h>
+#include <mediautils/TimeCheck.h>
+#include <system/audio.h>
+#include <system/audio_effects/effect_uuid.h>
+#include <utils/Log.h>
+
+#include "EffectHalAidl.h"
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+
+#include "effectsAidlConversion/AidlConversionAec.h"
+#include "effectsAidlConversion/AidlConversionAgc1.h"
+#include "effectsAidlConversion/AidlConversionAgc2.h"
+#include "effectsAidlConversion/AidlConversionBassBoost.h"
+#include "effectsAidlConversion/AidlConversionDownmix.h"
+#include "effectsAidlConversion/AidlConversionDynamicsProcessing.h"
+#include "effectsAidlConversion/AidlConversionEnvReverb.h"
+#include "effectsAidlConversion/AidlConversionEq.h"
+#include "effectsAidlConversion/AidlConversionHapticGenerator.h"
+#include "effectsAidlConversion/AidlConversionLoudnessEnhancer.h"
+#include "effectsAidlConversion/AidlConversionNoiseSuppression.h"
+#include "effectsAidlConversion/AidlConversionPresetReverb.h"
+#include "effectsAidlConversion/AidlConversionSpatializer.h"
+#include "effectsAidlConversion/AidlConversionVendorExtension.h"
+#include "effectsAidlConversion/AidlConversionVirtualizer.h"
+#include "effectsAidlConversion/AidlConversionVisualizer.h"
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Descriptor;
+using ::aidl::android::hardware::audio::effect::IEffect;
+using ::aidl::android::hardware::audio::effect::IFactory;
+
+namespace android {
+namespace effect {
+
+EffectHalAidl::EffectHalAidl(const std::shared_ptr<IFactory>& factory,
+                             const std::shared_ptr<IEffect>& effect, uint64_t effectId,
+                             int32_t sessionId, int32_t ioId, const Descriptor& desc)
+    : mFactory(factory),
+      mEffect(effect),
+      mEffectId(effectId),
+      mSessionId(sessionId),
+      mIoId(ioId),
+      mDesc(desc) {
+    createAidlConversion(effect, sessionId, ioId, desc);
+}
+
+EffectHalAidl::~EffectHalAidl() {
+    if (mFactory) {
+        mFactory->destroyEffect(mEffect);
+    }
+}
+
+status_t EffectHalAidl::createAidlConversion(
+        std::shared_ptr<IEffect> effect,
+        int32_t sessionId, int32_t ioId,
+        const Descriptor& desc) {
+    const auto& typeUuid = desc.common.id.type;
+    ALOGI("%s create UUID %s", __func__, typeUuid.toString().c_str());
+    if (typeUuid ==
+        ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler()) {
+        mConversion =
+                std::make_unique<android::effect::AidlConversionAec>(effect, sessionId, ioId, desc);
+    } else if (typeUuid == ::aidl::android::hardware::audio::effect::
+                                   getEffectTypeUuidAutomaticGainControlV1()) {
+        mConversion = std::make_unique<android::effect::AidlConversionAgc1>(effect, sessionId, ioId,
+                                                                            desc);
+    } else if (typeUuid == ::aidl::android::hardware::audio::effect::
+                                   getEffectTypeUuidAutomaticGainControlV2()) {
+        mConversion = std::make_unique<android::effect::AidlConversionAgc2>(effect, sessionId, ioId,
+                                                                            desc);
+    } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost()) {
+        mConversion = std::make_unique<android::effect::AidlConversionBassBoost>(effect, sessionId,
+                                                                                 ioId, desc);
+    } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix()) {
+        mConversion = std::make_unique<android::effect::AidlConversionDownmix>(effect, sessionId,
+                                                                               ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing()) {
+        mConversion =
+                std::make_unique<android::effect::AidlConversionDp>(effect, sessionId, ioId, desc);
+    } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb()) {
+        mConversion = std::make_unique<android::effect::AidlConversionEnvReverb>(effect, sessionId,
+                                                                                 ioId, desc);
+    } else if (typeUuid == ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer()) {
+        mConversion =
+                std::make_unique<android::effect::AidlConversionEq>(effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
+        mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
+                effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
+        mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
+                effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression()) {
+        mConversion = std::make_unique<android::effect::AidlConversionNoiseSuppression>(
+                effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb()) {
+        mConversion = std::make_unique<android::effect::AidlConversionPresetReverb>(
+                effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer()) {
+        mConversion = std::make_unique<android::effect::AidlConversionSpatializer>(
+                effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer()) {
+        mConversion = std::make_unique<android::effect::AidlConversionVirtualizer>(
+                effect, sessionId, ioId, desc);
+    } else if (typeUuid ==
+               ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer()) {
+        mConversion = std::make_unique<android::effect::AidlConversionVisualizer>(effect, sessionId,
+                                                                                  ioId, desc);
+    } else {
+        // For unknown UUID, use vendor extension implementation
+        mConversion = std::make_unique<android::effect::AidlConversionVendorExtension>(
+                effect, sessionId, ioId, desc);
+    }
+    return OK;
+}
+
+status_t EffectHalAidl::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+    mInBuffer = buffer;
+    return OK;
+}
+
+status_t EffectHalAidl::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+    mOutBuffer = buffer;
+    return OK;
+}
+
+
+// write to input FMQ here, wait for statusMQ STATUS_OK, and read from output FMQ
+status_t EffectHalAidl::process() {
+    size_t available = mInputQ->availableToWrite();
+    size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
+    if (floatsToWrite == 0) {
+        ALOGW("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
+              mInBuffer->getSize() / sizeof(float), available);
+        return INVALID_OPERATION;
+    }
+    if (!mInputQ->write((float*)mInBuffer->ptr(), floatsToWrite)) {
+        ALOGW("%s failed to write %zu into inputQ", __func__, floatsToWrite);
+        return INVALID_OPERATION;
+    }
+
+    IEffect::Status retStatus{};
+    if (!mStatusQ->readBlocking(&retStatus, 1) || retStatus.status != OK ||
+        (size_t)retStatus.fmqConsumed != floatsToWrite || retStatus.fmqProduced == 0) {
+        ALOGW("%s read status failed: %s", __func__, retStatus.toString().c_str());
+        return INVALID_OPERATION;
+    }
+
+    available = mOutputQ->availableToRead();
+    size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
+    if (floatsToRead == 0) {
+        ALOGW("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
+              mOutBuffer->getSize() / sizeof(float), available);
+        return INVALID_OPERATION;
+    }
+    if (!mOutputQ->read((float*)mOutBuffer->ptr(), floatsToRead)) {
+        ALOGW("%s failed to read %zu from outputQ", __func__, floatsToRead);
+        return INVALID_OPERATION;
+    }
+
+    ALOGD("%s %s consumed %zu produced %zu", __func__, mDesc.common.name.c_str(), floatsToWrite,
+          floatsToRead);
+    return OK;
+}
+
+// TODO: no one using, maybe deprecate this interface
+status_t EffectHalAidl::processReverse() {
+    ALOGW("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t EffectHalAidl::command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData,
+                                uint32_t* replySize, void* pReplyData) {
+    TIME_CHECK();
+    if (!mConversion) {
+        ALOGE("%s can not handle command %d when conversion not exist", __func__, cmdCode);
+        return INVALID_OPERATION;
+    }
+
+    status_t ret = mConversion->handleCommand(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+    // update FMQs when effect open successfully
+    if (ret == OK && cmdCode == EFFECT_CMD_INIT) {
+        const auto& retParam = mConversion->getEffectReturnParam();
+        mStatusQ = std::make_unique<StatusMQ>(retParam.statusMQ);
+        mInputQ = std::make_unique<DataMQ>(retParam.inputDataMQ);
+        mOutputQ = std::make_unique<DataMQ>(retParam.outputDataMQ);
+        if (!mStatusQ->isValid() || !mInputQ->isValid() || !mOutputQ->isValid()) {
+            ALOGE("%s return with invalid FMQ", __func__);
+            return NO_INIT;
+        }
+    }
+
+    return ret;
+}
+
+status_t EffectHalAidl::getDescriptor(effect_descriptor_t* pDescriptor) {
+    TIME_CHECK();
+    if (pDescriptor == nullptr) {
+        ALOGE("%s null descriptor pointer", __func__);
+        return BAD_VALUE;
+    }
+    Descriptor aidlDesc;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getDescriptor(&aidlDesc)));
+
+    *pDescriptor = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(aidlDesc));
+    return OK;
+}
+
+status_t EffectHalAidl::close() {
+    TIME_CHECK();
+    return statusTFromBinderStatus(mEffect->close());
+}
+
+status_t EffectHalAidl::dump(int fd) {
+    TIME_CHECK();
+    return mEffect->dump(fd, nullptr, 0);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
new file mode 100644
index 0000000..194150d
--- /dev/null
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <fmq/AidlMessageQueue.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <system/audio_effect.h>
+
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class EffectHalAidl : public EffectHalInterface {
+  public:
+    using StatusMQ = ::android::AidlMessageQueue<
+            ::aidl::android::hardware::audio::effect::IEffect::Status,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+    using DataMQ = ::android::AidlMessageQueue<
+            float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>;
+
+    // Set the input buffer.
+    status_t setInBuffer(const sp<EffectBufferHalInterface>& buffer) override;
+
+    // Set the output buffer.
+    status_t setOutBuffer(const sp<EffectBufferHalInterface>& buffer) override;
+
+    // Effect process function.
+    status_t process() override;
+
+    // Process reverse stream function. This function is used to pass
+    // a reference stream to the effect engine.
+    status_t processReverse() override;
+
+    // Send a command and receive a response to/from effect engine.
+    status_t command(uint32_t cmdCode, uint32_t cmdSize, void* pCmdData, uint32_t* replySize,
+                     void* pReplyData) override;
+
+    // Returns the effect descriptor.
+    status_t getDescriptor(effect_descriptor_t *pDescriptor) override;
+
+    // Free resources on the remote side.
+    status_t close() override;
+
+    // Whether it's a local implementation.
+    bool isLocal() const override { return false; }
+
+    status_t dump(int fd) override;
+
+    uint64_t effectId() const override { return mEffectId; }
+
+    const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> getIEffect() const {
+        return mEffect;
+    }
+
+    // for TIME_CHECK
+    const std::string getClassName() const { return "EffectHalAidl"; }
+
+  private:
+    friend class sp<EffectHalAidl>;
+
+    const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory> mFactory;
+    const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> mEffect;
+    const uint64_t mEffectId;
+    const int32_t mSessionId;
+    const int32_t mIoId;
+    const ::aidl::android::hardware::audio::effect::Descriptor mDesc;
+    std::unique_ptr<EffectConversionHelperAidl> mConversion;
+    std::unique_ptr<StatusMQ> mStatusQ;
+    std::unique_ptr<DataMQ> mInputQ, mOutputQ;
+
+    sp<EffectBufferHalInterface> mInBuffer, mOutBuffer;
+    effect_config_t mConfig;
+
+    status_t createAidlConversion(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+    // Can not be constructed directly by clients.
+    EffectHalAidl(
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IFactory>& factory,
+            const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& effect,
+            uint64_t effectId, int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc);
+    bool setEffectReverse(bool reverse);
+
+    // The destructor automatically releases the effect.
+    virtual ~EffectHalAidl();
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index 3956a6c..7ecdbd2 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -46,9 +46,6 @@
 using namespace ::android::hardware::audio::common::CPP_VERSION;
 using namespace ::android::hardware::audio::effect::CPP_VERSION;
 
-#define TIME_CHECK() auto timeCheck = \
-        mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
-
 EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
         : EffectConversionHelperHidl("EffectHalHidl"),
           mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
@@ -110,13 +107,13 @@
 }
 
 status_t EffectHalHidl::process() {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
 
     return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS));
 }
 
 status_t EffectHalHidl::processReverse() {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
 
     return processImpl(static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE));
 }
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
new file mode 100644
index 0000000..f289f24
--- /dev/null
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <algorithm>
+#include <cstdint>
+#include <memory>
+#define LOG_TAG "EffectsFactoryHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <android/binder_manager.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "EffectBufferHalAidl.h"
+#include "EffectHalAidl.h"
+#include "EffectsFactoryHalAidl.h"
+
+using ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid;
+using aidl::android::aidl_utils::statusTFromBinderStatus;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::media::audio::common::AudioUuid;
+using android::detail::AudioHalVersionInfo;
+
+namespace android {
+namespace effect {
+
+EffectsFactoryHalAidl::EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory)
+    : mFactory(effectsFactory),
+      mHalVersion(AudioHalVersionInfo(AudioHalVersionInfo::Type::AIDL, [this]() {
+          int32_t majorVersion = 0;
+          return (mFactory && mFactory->getInterfaceVersion(&majorVersion).isOk()) ? majorVersion
+                                                                                   : 0;
+      }())) {
+    ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
+}
+
+status_t EffectsFactoryHalAidl::queryNumberEffects(uint32_t *pNumEffects) {
+    if (pNumEffects == nullptr) {
+        return BAD_VALUE;
+    }
+
+    {
+        std::lock_guard lg(mLock);
+        RETURN_STATUS_IF_ERROR(queryEffectList_l());
+        *pNumEffects = mDescList->size();
+    }
+    ALOGI("%s %d", __func__, *pNumEffects);
+    return OK;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) {
+    if (pDescriptor == nullptr) {
+        return BAD_VALUE;
+    }
+
+    std::lock_guard lg(mLock);
+    RETURN_STATUS_IF_ERROR(queryEffectList_l());
+
+    auto listSize = mDescList->size();
+    if (index >= listSize) {
+        ALOGE("%s index %d exceed size DescList %zd", __func__, index, listSize);
+        return INVALID_OPERATION;
+    }
+
+    *pDescriptor = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(mDescList->at(index)));
+    return OK;
+}
+
+status_t EffectsFactoryHalAidl::getDescriptor(const effect_uuid_t* halUuid,
+                                              effect_descriptor_t* pDescriptor) {
+    if (halUuid == nullptr || pDescriptor == nullptr) {
+        return BAD_VALUE;
+    }
+
+    AudioUuid uuid = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halUuid));
+    std::lock_guard lg(mLock);
+    return getHalDescriptorWithImplUuid_l(uuid, pDescriptor);
+}
+
+status_t EffectsFactoryHalAidl::getDescriptors(const effect_uuid_t* halType,
+                                               std::vector<effect_descriptor_t>* descriptors) {
+    if (halType == nullptr || descriptors == nullptr) {
+        return BAD_VALUE;
+    }
+
+    AudioUuid type = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*halType));
+    std::lock_guard lg(mLock);
+    return getHalDescriptorWithTypeUuid_l(type, descriptors);
+}
+
+status_t EffectsFactoryHalAidl::createEffect(const effect_uuid_t* uuid, int32_t sessionId,
+                                             int32_t ioId, int32_t deviceId __unused,
+                                             sp<EffectHalInterface>* effect) {
+    if (uuid == nullptr || effect == nullptr) {
+        return BAD_VALUE;
+    }
+    if (sessionId == AUDIO_SESSION_DEVICE && ioId == AUDIO_IO_HANDLE_NONE) {
+        return INVALID_OPERATION;
+    }
+
+    ALOGI("%s session %d ioId %d", __func__, sessionId, ioId);
+
+    AudioUuid aidlUuid = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(*uuid));
+    std::shared_ptr<IEffect> aidlEffect;
+    Descriptor desc;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mFactory->createEffect(aidlUuid, &aidlEffect)));
+    if (aidlEffect == nullptr) {
+        ALOGE("%s IFactory::createFactory failed UUID %s", __func__, aidlUuid.toString().c_str());
+        return NAME_NOT_FOUND;
+    }
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(aidlEffect->getDescriptor(&desc)));
+
+    uint64_t effectId;
+    {
+        std::lock_guard lg(mLock);
+        effectId = ++mEffectIdCounter;
+    }
+
+    *effect = sp<EffectHalAidl>::make(mFactory, aidlEffect, effectId, sessionId, ioId, desc);
+    return OK;
+}
+
+status_t EffectsFactoryHalAidl::dumpEffects(int fd) {
+    // TODO: add proxy dump here because AIDL service EffectFactory doesn't have proxy handle
+    return mFactory->dump(fd, nullptr, 0);
+}
+
+status_t EffectsFactoryHalAidl::allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) {
+    ALOGI("%s size %zu buffer %p", __func__, size, buffer);
+    return EffectBufferHalAidl::allocate(size, buffer);
+}
+
+status_t EffectsFactoryHalAidl::mirrorBuffer(void* external, size_t size,
+                                             sp<EffectBufferHalInterface>* buffer) {
+    ALOGI("%s extern %p size %zu buffer %p", __func__, external, size, buffer);
+    return EffectBufferHalAidl::mirror(external, size, buffer);
+}
+
+AudioHalVersionInfo EffectsFactoryHalAidl::getHalVersion() const {
+    return mHalVersion;
+}
+
+status_t EffectsFactoryHalAidl::queryEffectList_l() {
+    if (!mDescList) {
+        std::vector<Descriptor> list;
+        auto status = mFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &list);
+        if (!status.isOk()) {
+            ALOGE("%s IFactory::queryEffects failed %s", __func__, status.getDescription().c_str());
+            return status.getStatus();
+        }
+
+        mDescList = std::make_unique<std::vector<Descriptor>>(list);
+    }
+    return OK;
+}
+
+status_t EffectsFactoryHalAidl::getHalDescriptorWithImplUuid_l(const AudioUuid& uuid,
+                                                               effect_descriptor_t* pDescriptor) {
+    if (pDescriptor == nullptr) {
+        return BAD_VALUE;
+    }
+    if (!mDescList) {
+        RETURN_STATUS_IF_ERROR(queryEffectList_l());
+    }
+
+    auto matchIt = std::find_if(mDescList->begin(), mDescList->end(),
+                                 [&](const auto& desc) { return desc.common.id.uuid == uuid; });
+    if (matchIt == mDescList->end()) {
+        ALOGE("%s UUID %s not found", __func__, uuid.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    *pDescriptor = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_Descriptor_effect_descriptor(*matchIt));
+    return OK;
+}
+
+status_t EffectsFactoryHalAidl::getHalDescriptorWithTypeUuid_l(
+        const AudioUuid& type, std::vector<effect_descriptor_t>* descriptors) {
+    if (descriptors == nullptr) {
+        return BAD_VALUE;
+    }
+    if (!mDescList) {
+        RETURN_STATUS_IF_ERROR(queryEffectList_l());
+    }
+    std::vector<Descriptor> result;
+    std::copy_if(mDescList->begin(), mDescList->end(), std::back_inserter(result),
+                 [&](auto& desc) { return desc.common.id.type == type; });
+    if (result.size() == 0) {
+        ALOGE("%s type UUID %s not found", __func__, type.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    *descriptors = VALUE_OR_RETURN_STATUS(
+            aidl::android::convertContainer<std::vector<effect_descriptor_t>>(
+                    result, ::aidl::android::aidl2legacy_Descriptor_effect_descriptor));
+    return OK;
+}
+
+} // namespace effect
+
+// When a shared library is built from a static library, even explicit
+// exports from a static library are optimized out unless actually used by
+// the shared library. See EffectsFactoryHalEntry.cpp.
+extern "C" void* createIEffectsFactoryImpl() {
+    auto serviceName = std::string(IFactory::descriptor) + "/default";
+    auto service = IFactory::fromBinder(
+            ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
+    if (!service) {
+        ALOGE("%s binder service %s not exist", __func__, serviceName.c_str());
+        return nullptr;
+    }
+    return new effect::EffectsFactoryHalAidl(service);
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalAidl.h b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
new file mode 100644
index 0000000..9c3643b
--- /dev/null
+++ b/media/libaudiohal/impl/EffectsFactoryHalAidl.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstddef>
+#include <memory>
+#include <mutex>
+
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <android-base/thread_annotations.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <system/thread_defs.h>
+
+namespace android {
+namespace effect {
+
+using namespace aidl::android::hardware::audio::effect;
+
+class EffectsFactoryHalAidl final : public EffectsFactoryHalInterface {
+  public:
+    explicit EffectsFactoryHalAidl(std::shared_ptr<IFactory> effectsFactory);
+
+    // Returns the number of different effects in all loaded libraries.
+    status_t queryNumberEffects(uint32_t *pNumEffects) override;
+
+    // Returns a descriptor of the next available effect.
+    status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) override;
+
+    status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+                           effect_descriptor_t* pDescriptor) override;
+
+    status_t getDescriptors(const effect_uuid_t* pEffectType,
+                            std::vector<effect_descriptor_t>* descriptors) override;
+
+    // Creates an effect engine of the specified type.
+    // To release the effect engine, it is necessary to release references to the returned effect
+    // object.
+    status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+                          int32_t deviceId, sp<EffectHalInterface>* effect) override;
+
+    status_t dumpEffects(int fd) override;
+
+    status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
+    status_t mirrorBuffer(void* external, size_t size,
+                          sp<EffectBufferHalInterface>* buffer) override;
+
+    detail::AudioHalVersionInfo getHalVersion() const override;
+
+    // for TIME_CHECK
+    const std::string getClassName() const { return "EffectHalAidl"; }
+
+  private:
+    std::mutex mLock;
+    const std::shared_ptr<IFactory> mFactory;
+    uint64_t mEffectIdCounter GUARDED_BY(mLock) = 0; // Align with HIDL (0 is INVALID_ID)
+    std::unique_ptr<std::vector<Descriptor>> mDescList GUARDED_BY(mLock) = nullptr;
+    const detail::AudioHalVersionInfo mHalVersion;
+
+    virtual ~EffectsFactoryHalAidl() = default;
+    status_t queryEffectList_l() REQUIRES(mLock);
+    status_t getHalDescriptorWithImplUuid_l(
+            const aidl::android::media::audio::common::AudioUuid& uuid,
+            effect_descriptor_t* pDescriptor) REQUIRES(mLock);
+    status_t getHalDescriptorWithTypeUuid_l(
+            const aidl::android::media::audio::common::AudioUuid& type,
+            std::vector<effect_descriptor_t>* descriptors) REQUIRES(mLock);
+};
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp b/media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
similarity index 94%
rename from media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
rename to media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
index 2c6f2c6..f6ad99a 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidlEntry.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalEntry.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "android/media/AudioHalVersion.h"
+
 extern "C" void* createIEffectsFactoryImpl();
 
 extern "C" __attribute__((visibility("default"))) void* createIEffectsFactory() {
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index 3470380..172ebdf 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -31,6 +31,9 @@
 #include "EffectHalHidl.h"
 #include "EffectsFactoryHalHidl.h"
 
+#include "android/media/AudioHalVersion.h"
+
+using ::android::detail::AudioHalVersionInfo;
 using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
 using ::android::hardware::audio::effect::CPP_VERSION::implementation::EffectUtils;
 using ::android::hardware::Return;
@@ -77,7 +80,7 @@
 EffectsFactoryHalHidl::EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory)
         : EffectConversionHelperHidl("EffectsFactory"), mCache(new EffectDescriptorCache) {
     ALOG_ASSERT(effectsFactory != nullptr, "Provided IEffectsFactory service is NULL");
-    mEffectsFactory = effectsFactory;
+    mEffectsFactory = std::move(effectsFactory);
 }
 
 status_t EffectsFactoryHalHidl::queryNumberEffects(uint32_t *pNumEffects) {
@@ -221,11 +224,15 @@
     return EffectBufferHalHidl::mirror(external, size, buffer);
 }
 
+AudioHalVersionInfo EffectsFactoryHalHidl::getHalVersion() const {
+    return AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, MAJOR_VERSION, MINOR_VERSION);
+}
+
 } // namespace effect
 
 // When a shared library is built from a static library, even explicit
 // exports from a static library are optimized out unless actually used by
-// the shared library. See EffectsFactoryHalHidlEntry.cpp.
+// the shared library. See EffectsFactoryHalEntry.cpp.
 extern "C" void* createIEffectsFactoryImpl() {
     auto service = hardware::audio::effect::CPP_VERSION::IEffectsFactory::getService();
     return service ? new effect::EffectsFactoryHalHidl(service) : nullptr;
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 7ccddc6..9875154 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
+#pragma once
 
 #include <memory>
 
@@ -32,39 +31,37 @@
 
 class EffectDescriptorCache;
 
-class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public EffectConversionHelperHidl
-{
+class EffectsFactoryHalHidl final : public EffectsFactoryHalInterface,
+                                    public EffectConversionHelperHidl {
   public:
     EffectsFactoryHalHidl(sp<IEffectsFactory> effectsFactory);
 
     // Returns the number of different effects in all loaded libraries.
-    virtual status_t queryNumberEffects(uint32_t *pNumEffects);
+    status_t queryNumberEffects(uint32_t *pNumEffects) override;
 
     // Returns a descriptor of the next available effect.
-    virtual status_t getDescriptor(uint32_t index,
-            effect_descriptor_t *pDescriptor);
+    status_t getDescriptor(uint32_t index, effect_descriptor_t* pDescriptor) override;
 
-    virtual status_t getDescriptor(const effect_uuid_t *pEffectUuid,
-            effect_descriptor_t *pDescriptor);
+    status_t getDescriptor(const effect_uuid_t* pEffectUuid,
+                           effect_descriptor_t* pDescriptor) override;
 
-    virtual status_t getDescriptors(const effect_uuid_t *pEffectType,
-                                    std::vector<effect_descriptor_t> *descriptors);
+    status_t getDescriptors(const effect_uuid_t* pEffectType,
+                            std::vector<effect_descriptor_t>* descriptors) override;
 
     // Creates an effect engine of the specified type.
     // To release the effect engine, it is necessary to release references
     // to the returned effect object.
-    virtual status_t createEffect(const effect_uuid_t *pEffectUuid,
-            int32_t sessionId, int32_t ioId, int32_t deviceId,
-            sp<EffectHalInterface> *effect);
+    status_t createEffect(const effect_uuid_t* pEffectUuid, int32_t sessionId, int32_t ioId,
+                          int32_t deviceId, sp<EffectHalInterface>* effect) override;
 
-    virtual status_t dumpEffects(int fd);
-
-    virtual float getHalVersion() { return MAJOR_VERSION + (float)MINOR_VERSION / 10; }
+    status_t dumpEffects(int fd) override;
 
     status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
     status_t mirrorBuffer(void* external, size_t size,
                           sp<EffectBufferHalInterface>* buffer) override;
 
+    android::detail::AudioHalVersionInfo getHalVersion() const override;
+
   private:
     sp<IEffectsFactory> mEffectsFactory;
     std::unique_ptr<EffectDescriptorCache> mCache;
@@ -72,5 +69,3 @@
 
 } // namespace effect
 } // namespace android
-
-#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/StreamHalAidl.cpp b/media/libaudiohal/impl/StreamHalAidl.cpp
new file mode 100644
index 0000000..cbc1578
--- /dev/null
+++ b/media/libaudiohal/impl/StreamHalAidl.cpp
@@ -0,0 +1,940 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "StreamHalAidl"
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <cstdint>
+
+#include <audio_utils/clock.h>
+#include <media/AidlConversion.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionUtil.h>
+#include <media/AudioParameter.h>
+#include <mediautils/TimeCheck.h>
+#include <system/audio.h>
+#include <utils/Log.h>
+
+#include "DeviceHalAidl.h"
+#include "StreamHalAidl.h"
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::common::PlaybackTrackMetadata;
+using ::aidl::android::hardware::audio::common::RecordTrackMetadata;
+using ::aidl::android::hardware::audio::core::IStreamCommon;
+using ::aidl::android::hardware::audio::core::IStreamIn;
+using ::aidl::android::hardware::audio::core::IStreamOut;
+using ::aidl::android::hardware::audio::core::StreamDescriptor;
+using ::aidl::android::media::audio::common::MicrophoneDynamicInfo;
+
+namespace android {
+
+using HalCommand = StreamDescriptor::Command;
+namespace {
+template<HalCommand::Tag cmd> HalCommand makeHalCommand() {
+    return HalCommand::make<cmd>(::aidl::android::media::audio::common::Void{});
+}
+template<HalCommand::Tag cmd, typename T> HalCommand makeHalCommand(T data) {
+    return HalCommand::make<cmd>(data);
+}
+}  // namespace
+
+// static
+template<class T>
+std::shared_ptr<IStreamCommon> StreamHalAidl::getStreamCommon(const std::shared_ptr<T>& stream) {
+    std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> streamCommon;
+    if (stream != nullptr) {
+        if (ndk::ScopedAStatus status = stream->getStreamCommon(&streamCommon);
+                !status.isOk()) {
+            ALOGE("%s: failed to retrieve IStreamCommon instance: %s", __func__,
+                    status.getDescription().c_str());
+        }
+    }
+    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)
+        : ConversionHelperAidl(className),
+          mIsInput(isInput),
+          mConfig(configToBase(config)),
+          mContext(std::move(context)),
+          mStream(stream) {
+    {
+        std::lock_guard l(mLock);
+        mLastReply.latencyMs = nominalLatency;
+    }
+    // Instrument audio signal power logging.
+    // Note: This assumes channel mask, format, and sample rate do not change after creation.
+    if (audio_config_base_t config = AUDIO_CONFIG_BASE_INITIALIZER;
+            /* mStreamPowerLog.isUserDebugOrEngBuild() && */
+            StreamHalAidl::getAudioProperties(&config) == NO_ERROR) {
+        mStreamPowerLog.init(config.sample_rate, config.channel_mask, config.format);
+    }
+}
+
+StreamHalAidl::~StreamHalAidl() {
+    if (mStream != nullptr) {
+        ndk::ScopedAStatus status = mStream->close();
+        ALOGE_IF(!status.isOk(), "%s: status %s", __func__, status.getDescription().c_str());
+    }
+}
+
+status_t StreamHalAidl::getBufferSize(size_t *size) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (size == nullptr) {
+        return BAD_VALUE;
+    }
+    if (mContext.getFrameSizeBytes() == 0 || mContext.getBufferSizeFrames() == 0 ||
+            !mStream) {
+        return NO_INIT;
+    }
+    *size = mContext.getBufferSizeBytes();
+    return OK;
+}
+
+status_t StreamHalAidl::getAudioProperties(audio_config_base_t *configBase) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (configBase == nullptr) {
+        return BAD_VALUE;
+    }
+    if (!mStream) return NO_INIT;
+    *configBase = mConfig;
+    return OK;
+}
+
+namespace {
+
+// 'action' must accept a value of type 'T' and return 'status_t'.
+// The function returns 'true' if the parameter was found, and the action has succeeded.
+// The function returns 'false' if the parameter was not found.
+// Any errors get propagated, if there are errors it means the parameter was found.
+template<typename T, typename F>
+error::Result<bool> filterOutAndProcessParameter(
+        AudioParameter& parameters, const String8& key, const F& action) {
+    if (parameters.containsKey(key)) {
+        T value;
+        status_t status = parameters.get(key, value);
+        if (status == OK) {
+            parameters.remove(key);
+            status = action(value);
+            if (status == OK) return true;
+        }
+        return base::unexpected(status);
+    }
+    return false;
+}
+
+}  // namespace
+
+status_t StreamHalAidl::setParameters(const String8& kvPairs) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+
+    AudioParameter parameters(kvPairs);
+    ALOGD("%s: parameters: %s", __func__, parameters.toString().c_str());
+
+    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                    parameters, String8(AudioParameter::keyStreamHwAvSync),
+            [&](int hwAvSyncId) {
+                return statusTFromBinderStatus(mStream->updateHwAvSyncId(hwAvSyncId));
+            }));
+
+    ALOGW_IF(parameters.size() != 0, "%s: unknown parameters, ignored: %s",
+            __func__, parameters.toString().c_str());
+    return OK;
+}
+
+status_t StreamHalAidl::getParameters(const String8& keys __unused, String8 *values) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    values->clear();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::getFrameSize(size_t *size) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (size == nullptr) {
+        return BAD_VALUE;
+    }
+    if (mContext.getFrameSizeBytes() == 0 || !mStream) {
+        return NO_INIT;
+    }
+    *size = mContext.getFrameSizeBytes();
+    return OK;
+}
+
+status_t StreamHalAidl::addEffect(sp<EffectHalInterface> effect __unused) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::removeEffect(sp<EffectHalInterface> effect __unused) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::standby() {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    const auto state = getState();
+    StreamDescriptor::Reply reply;
+    switch (state) {
+        case StreamDescriptor::State::ACTIVE:
+            if (status_t status = pause(&reply); status != OK) return status;
+            if (reply.state != StreamDescriptor::State::PAUSED) {
+                ALOGE("%s: unexpected stream state: %s (expected PAUSED)",
+                        __func__, toString(reply.state).c_str());
+                return INVALID_OPERATION;
+            }
+            FALLTHROUGH_INTENDED;
+        case StreamDescriptor::State::PAUSED:
+        case StreamDescriptor::State::DRAIN_PAUSED:
+            if (mIsInput) return flush();
+            if (status_t status = flush(&reply); status != OK) return status;
+            if (reply.state != StreamDescriptor::State::IDLE) {
+                ALOGE("%s: unexpected stream state: %s (expected IDLE)",
+                        __func__, toString(reply.state).c_str());
+                return INVALID_OPERATION;
+            }
+            FALLTHROUGH_INTENDED;
+        case StreamDescriptor::State::IDLE:
+            if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::standby>(),
+                            &reply, true /*safeFromNonWorkerThread*/); status != OK) {
+                return status;
+            }
+            if (reply.state != StreamDescriptor::State::STANDBY) {
+                ALOGE("%s: unexpected stream state: %s (expected STANDBY)",
+                        __func__, 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());
+            return INVALID_OPERATION;
+    }
+}
+
+status_t StreamHalAidl::dump(int fd, const Vector<String16>& args) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return mStream->dump(fd, Args(args).args(), args.size());
+}
+
+status_t StreamHalAidl::start() {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::stop() {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::getLatency(uint32_t *latency) {
+    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (!mStream) return NO_INIT;
+    StreamDescriptor::Reply reply;
+    if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+        return status;
+    }
+    *latency = std::max<int32_t>(0, reply.latencyMs);
+    return OK;
+}
+
+status_t StreamHalAidl::getObservablePosition(int64_t *frames, int64_t *timestamp) {
+    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (!mStream) return NO_INIT;
+    StreamDescriptor::Reply reply;
+    if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+        return status;
+    }
+    *frames = reply.observable.frames;
+    *timestamp = reply.observable.timeNs;
+    return OK;
+}
+
+status_t StreamHalAidl::getXruns(int32_t *frames) {
+    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    if (!mStream) return NO_INIT;
+    StreamDescriptor::Reply reply;
+    if (status_t status = updateCountersIfNeeded(&reply); status != OK) {
+        return status;
+    }
+    *frames = reply.xrunFrames;
+    return OK;
+}
+
+status_t StreamHalAidl::transfer(void *buffer, size_t bytes, size_t *transferred) {
+    ALOGV("%p %s::%s", this, getClassName().c_str(), __func__);
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
+    if (!mStream || mContext.getDataMQ() == nullptr) return NO_INIT;
+    mWorkerTid.store(gettid(), std::memory_order_release);
+    // Switch the stream into an active state if needed.
+    // Note: in future we may add support for priming the audio pipeline
+    // with data prior to enabling output (thus we can issue a "burst" command in the "standby"
+    // stream state), however this scenario wasn't supported by the HIDL HAL.
+    if (getState() == StreamDescriptor::State::STANDBY) {
+        StreamDescriptor::Reply reply;
+        if (status_t status = sendCommand(makeHalCommand<HalCommand::Tag::start>(), &reply);
+                status != OK) {
+            return status;
+        }
+        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());
+            return INVALID_OPERATION;
+        }
+    }
+    if (!mIsInput) {
+        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);
+            return NOT_ENOUGH_DATA;
+        }
+    }
+    StreamDescriptor::Reply reply;
+    if (status_t status = sendCommand(burst, &reply); status != OK) {
+        return status;
+    }
+    *transferred = reply.fmqByteCount;
+    if (mIsInput) {
+        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();
+                toRead != 0 && !mContext.getDataMQ()->read(static_cast<int8_t*>(buffer), toRead)) {
+            ALOGE("%s: failed to read %zu bytes to data MQ", __func__, toRead);
+            return NOT_ENOUGH_DATA;
+        }
+    }
+    mStreamPowerLog.log(buffer, *transferred);
+    return OK;
+}
+
+status_t StreamHalAidl::pause(StreamDescriptor::Reply* reply) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return sendCommand(makeHalCommand<HalCommand::Tag::pause>(), reply,
+            true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
+}
+
+status_t StreamHalAidl::resume(StreamDescriptor::Reply* reply) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (mIsInput) {
+        return sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), reply);
+    } else {
+        if (mContext.isAsynchronous()) {
+            // Handle pause-flush-resume sequence. 'flush' from PAUSED goes to
+            // IDLE. We move here from IDLE to ACTIVE (same as 'start' from PAUSED).
+            const auto state = getState();
+            if (state == StreamDescriptor::State::IDLE) {
+                StreamDescriptor::Reply localReply{};
+                StreamDescriptor::Reply* innerReply = reply ?: &localReply;
+                if (status_t status =
+                        sendCommand(makeHalCommand<HalCommand::Tag::burst>(0), innerReply);
+                        status != OK) {
+                    return status;
+                }
+                if (innerReply->state != StreamDescriptor::State::ACTIVE) {
+                    ALOGE("%s: unexpected stream state: %s (expected ACTIVE)",
+                            __func__, toString(innerReply->state).c_str());
+                    return INVALID_OPERATION;
+                }
+                return OK;
+            }
+        }
+        return sendCommand(makeHalCommand<HalCommand::Tag::start>(), reply);
+    }
+}
+
+status_t StreamHalAidl::drain(bool earlyNotify, StreamDescriptor::Reply* reply) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return sendCommand(makeHalCommand<HalCommand::Tag::drain>(
+                    mIsInput ? StreamDescriptor::DrainMode::DRAIN_UNSPECIFIED :
+                    earlyNotify ? StreamDescriptor::DrainMode::DRAIN_EARLY_NOTIFY :
+                    StreamDescriptor::DrainMode::DRAIN_ALL), reply,
+                    true /*safeFromNonWorkerThread*/);
+}
+
+status_t StreamHalAidl::flush(StreamDescriptor::Reply* reply) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return sendCommand(makeHalCommand<HalCommand::Tag::flush>(), reply,
+            true /*safeFromNonWorkerThread*/);  // The workers stops its I/O activity first.
+}
+
+status_t StreamHalAidl::exit() {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::createMmapBuffer(int32_t minSizeFrames __unused,
+                                  struct audio_mmap_buffer_info *info __unused) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::getMmapPosition(struct audio_mmap_position *position __unused) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamHalAidl::setHalThreadPriority(int priority __unused) {
+    // Obsolete, must be done by the HAL module.
+    return OK;
+}
+
+status_t StreamHalAidl::getHalPid(pid_t *pid __unused) {
+    ALOGD("%p %s::%s", this, getClassName().c_str(), __func__);
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+bool StreamHalAidl::requestHalThreadPriority(pid_t threadPid __unused, pid_t threadId __unused) {
+    // Obsolete, must be done by the HAL module.
+    return true;
+}
+
+status_t StreamHalAidl::legacyCreateAudioPatch(const struct audio_port_config& port __unused,
+                                               std::optional<audio_source_t> source __unused,
+                                               audio_devices_t type __unused) {
+    // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
+    return INVALID_OPERATION;
+}
+
+status_t StreamHalAidl::legacyReleaseAudioPatch() {
+    // Obsolete since 'DeviceHalAidl.supportsAudioPatches' always returns 'true'.
+    return INVALID_OPERATION;
+}
+
+status_t StreamHalAidl::sendCommand(
+        const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+        ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply,
+        bool safeFromNonWorkerThread) {
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
+    if (!safeFromNonWorkerThread) {
+        const pid_t workerTid = mWorkerTid.load(std::memory_order_acquire);
+        LOG_ALWAYS_FATAL_IF(workerTid != gettid(),
+                "%s %s: must be invoked from the worker thread (%d)",
+                __func__, command.toString().c_str(), workerTid);
+    }
+    if (!mContext.getCommandMQ()->writeBlocking(&command, 1)) {
+        ALOGE("%s: failed to write command %s to MQ", __func__, command.toString().c_str());
+        return NOT_ENOUGH_DATA;
+    }
+    StreamDescriptor::Reply localReply{};
+    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());
+        return NOT_ENOUGH_DATA;
+    }
+    {
+        std::lock_guard l(mLock);
+        mLastReply = *reply;
+    }
+    switch (reply->status) {
+        case STATUS_OK: return OK;
+        case STATUS_BAD_VALUE: return BAD_VALUE;
+        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());
+            return INVALID_OPERATION;
+    }
+}
+
+status_t StreamHalAidl::updateCountersIfNeeded(
+        ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply) {
+    if (mWorkerTid.load(std::memory_order_acquire) == gettid()) {
+        if (const auto state = getState(); state != StreamDescriptor::State::ACTIVE &&
+                state != StreamDescriptor::State::DRAINING &&
+                state != StreamDescriptor::State::TRANSFERRING) {
+            return sendCommand(makeHalCommand<HalCommand::Tag::getStatus>(), reply);
+        }
+    }
+    if (reply != nullptr) {
+        std::lock_guard l(mLock);
+        *reply = mLastReply;
+    }
+    return OK;
+}
+
+// static
+ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
+StreamOutHalAidl::legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy) {
+    ::aidl::android::hardware::audio::common::SourceMetadata aidl;
+    aidl.tracks = VALUE_OR_RETURN(
+            ::aidl::android::convertContainer<std::vector<PlaybackTrackMetadata>>(
+                    legacy.tracks,
+                    ::aidl::android::legacy2aidl_playback_track_metadata_v7_PlaybackTrackMetadata));
+    return aidl;
+}
+
+StreamOutHalAidl::StreamOutHalAidl(
+        const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+        const std::shared_ptr<IStreamOut>& stream, const sp<CallbackBroker>& callbackBroker)
+        : StreamHalAidl("StreamOutHalAidl", false /*isInput*/, config, nominalLatency,
+                std::move(context), getStreamCommon(stream)),
+          mStream(stream), mCallbackBroker(callbackBroker) {
+    // Initialize the offload metadata
+    mOffloadMetadata.sampleRate = static_cast<int32_t>(config.sample_rate);
+    mOffloadMetadata.channelMask = VALUE_OR_FATAL(
+            ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                    config.channel_mask, false));
+    mOffloadMetadata.averageBitRatePerSecond = static_cast<int32_t>(config.offload_info.bit_rate);
+}
+
+StreamOutHalAidl::~StreamOutHalAidl() {
+    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+        broker->clearCallbacks(this);
+    }
+}
+
+status_t StreamOutHalAidl::setParameters(const String8& kvPairs) {
+    if (!mStream) return NO_INIT;
+
+    AudioParameter parameters(kvPairs);
+    ALOGD("%s parameters: %s", __func__, parameters.toString().c_str());
+
+    if (status_t status = filterAndUpdateOffloadMetadata(parameters); status != OK) {
+        ALOGW("%s filtering or updating offload metadata failed: %d", __func__, status);
+    }
+
+    return StreamHalAidl::setParameters(parameters.toString());
+}
+
+status_t StreamOutHalAidl::getLatency(uint32_t *latency) {
+    return StreamHalAidl::getLatency(latency);
+}
+
+status_t StreamOutHalAidl::setVolume(float left, float right) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    return statusTFromBinderStatus(mStream->setHwVolume({left, right}));
+}
+
+status_t StreamOutHalAidl::selectPresentation(int presentationId __unused, int programId __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamOutHalAidl::write(const void *buffer, size_t bytes, size_t *written) {
+    if (buffer == nullptr || written == nullptr) {
+        return BAD_VALUE;
+    }
+    // For the output scenario, 'transfer' does not modify the buffer.
+    return transfer(const_cast<void*>(buffer), bytes, written);
+}
+
+status_t StreamOutHalAidl::getRenderPosition(uint32_t *dspFrames) {
+    if (dspFrames == nullptr) {
+        return BAD_VALUE;
+    }
+    int64_t aidlFrames = 0, aidlTimestamp = 0;
+    if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
+        return OK;
+    }
+    *dspFrames = std::clamp<int64_t>(aidlFrames, 0, UINT32_MAX);
+    return OK;
+}
+
+status_t StreamOutHalAidl::getNextWriteTimestamp(int64_t *timestamp __unused) {
+    // Obsolete, use getPresentationPosition.
+    return INVALID_OPERATION;
+}
+
+status_t StreamOutHalAidl::setCallback(wp<StreamOutHalInterfaceCallback> callback) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (!mContext.isAsynchronous()) {
+        ALOGE("%s: the callback is intended for asynchronous streams only", __func__);
+        return INVALID_OPERATION;
+    }
+    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+        if (auto cb = callback.promote(); cb != nullptr) {
+            broker->setStreamOutCallback(this, cb);
+        } else {
+            // It is expected that the framework never passes a null pointer.
+            // In the AIDL model callbacks can't be "unregistered".
+            LOG_ALWAYS_FATAL("%s: received an expired or null callback pointer", __func__);
+        }
+    }
+    return OK;
+}
+
+status_t StreamOutHalAidl::supportsPauseAndResume(bool *supportsPause, bool *supportsResume) {
+    if (supportsPause == nullptr || supportsResume == nullptr) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    *supportsPause = *supportsResume = true;
+    return OK;
+}
+
+status_t StreamOutHalAidl::pause() {
+    return StreamHalAidl::pause();
+}
+
+status_t StreamOutHalAidl::resume() {
+    return StreamHalAidl::resume();
+}
+
+status_t StreamOutHalAidl::supportsDrain(bool *supportsDrain) {
+    if (supportsDrain == nullptr) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    *supportsDrain = true;
+    return OK;
+}
+
+status_t StreamOutHalAidl::drain(bool earlyNotify) {
+    return StreamHalAidl::drain(earlyNotify);
+}
+
+status_t StreamOutHalAidl::flush() {
+    return StreamHalAidl::flush();
+}
+
+status_t StreamOutHalAidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
+    if (frames == nullptr || timestamp == nullptr) {
+        return BAD_VALUE;
+    }
+    int64_t aidlFrames = 0, aidlTimestamp = 0;
+    if (status_t status = getObservablePosition(&aidlFrames, &aidlTimestamp); status != OK) {
+        return status;
+    }
+    *frames = std::max<int64_t>(0, aidlFrames);
+    timestamp->tv_sec = aidlTimestamp / NANOS_PER_SECOND;
+    timestamp->tv_nsec = aidlTimestamp - timestamp->tv_sec * NANOS_PER_SECOND;
+    return OK;
+}
+
+status_t StreamOutHalAidl::updateSourceMetadata(
+        const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ::aidl::android::hardware::audio::common::SourceMetadata aidlMetadata =
+              VALUE_OR_RETURN_STATUS(legacy2aidl_SourceMetadata(sourceMetadata));
+    return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
+}
+
+status_t StreamOutHalAidl::getDualMonoMode(audio_dual_mono_mode_t* mode __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamOutHalAidl::setDualMonoMode(audio_dual_mono_mode_t mode __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamOutHalAidl::getAudioDescriptionMixLevel(float* leveldB __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamOutHalAidl::setAudioDescriptionMixLevel(float leveldB __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamOutHalAidl::getPlaybackRateParameters(
+        audio_playback_rate_t* playbackRate __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return BAD_VALUE;
+}
+
+status_t StreamOutHalAidl::setPlaybackRateParameters(
+        const audio_playback_rate_t& playbackRate __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return BAD_VALUE;
+}
+
+status_t StreamOutHalAidl::setEventCallback(
+        const sp<StreamOutHalInterfaceEventCallback>& callback) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+        broker->setStreamOutEventCallback(this, callback);
+    }
+    return OK;
+}
+
+status_t StreamOutHalAidl::setLatencyMode(audio_latency_mode_t mode __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+};
+
+status_t StreamOutHalAidl::getRecommendedLatencyModes(
+        std::vector<audio_latency_mode_t> *modes __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+};
+
+status_t StreamOutHalAidl::setLatencyModeCallback(
+        const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    if (auto broker = mCallbackBroker.promote(); broker != nullptr) {
+        broker->setStreamOutLatencyModeCallback(this, callback);
+    }
+    return OK;
+};
+
+status_t StreamOutHalAidl::exit() {
+    return StreamHalAidl::exit();
+}
+
+status_t StreamOutHalAidl::filterAndUpdateOffloadMetadata(AudioParameter &parameters) {
+    TIME_CHECK();
+    bool updateMetadata = false;
+    if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                parameters, String8(AudioParameter::keyOffloadCodecAverageBitRate),
+                [&](int value) {
+                    return value > 0 ?
+                            mOffloadMetadata.averageBitRatePerSecond = value, OK : BAD_VALUE;
+                }))) {
+        updateMetadata = true;
+    }
+    if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                parameters, String8(AudioParameter::keyOffloadCodecSampleRate),
+                [&](int value) {
+                    return value > 0 ? mOffloadMetadata.sampleRate = value, OK : BAD_VALUE;
+                }))) {
+        updateMetadata = true;
+    }
+    if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                parameters, String8(AudioParameter::keyOffloadCodecChannels),
+                [&](int value) -> status_t {
+                    if (value > 0) {
+                        audio_channel_mask_t channel_mask = audio_channel_out_mask_from_count(
+                                static_cast<uint32_t>(value));
+                        if (channel_mask == AUDIO_CHANNEL_INVALID) return BAD_VALUE;
+                        mOffloadMetadata.channelMask = VALUE_OR_RETURN_STATUS(
+                                ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                                        channel_mask, false /*isInput*/));
+                    }
+                    return BAD_VALUE;
+                }))) {
+        updateMetadata = true;
+    }
+    if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                parameters, String8(AudioParameter::keyOffloadCodecDelaySamples),
+                [&](int value) {
+                    // The legacy keys are misnamed, the value is in frames.
+                    return value > 0 ? mOffloadMetadata.delayFrames = value, OK : BAD_VALUE;
+                }))) {
+        updateMetadata = true;
+    }
+    if (VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<int>(
+                parameters, String8(AudioParameter::keyOffloadCodecPaddingSamples),
+                [&](int value) {
+                    // The legacy keys are misnamed, the value is in frames.
+                    return value > 0 ? mOffloadMetadata.paddingFrames = value, OK : BAD_VALUE;
+                }))) {
+        updateMetadata = true;
+    }
+    if (updateMetadata) {
+        ALOGD("%s set offload metadata %s", __func__, mOffloadMetadata.toString().c_str());
+        if (status_t status = statusTFromBinderStatus(
+                        mStream->updateOffloadMetadata(mOffloadMetadata)); status != OK) {
+            ALOGE("%s: updateOffloadMetadata failed %d", __func__, status);
+            return status;
+        }
+    }
+    return OK;
+}
+
+// static
+ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
+StreamInHalAidl::legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy) {
+    ::aidl::android::hardware::audio::common::SinkMetadata aidl;
+    aidl.tracks = VALUE_OR_RETURN(
+            ::aidl::android::convertContainer<std::vector<RecordTrackMetadata>>(
+                    legacy.tracks,
+                    ::aidl::android::legacy2aidl_record_track_metadata_v7_RecordTrackMetadata));
+    return aidl;
+}
+
+StreamInHalAidl::StreamInHalAidl(
+        const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+        const std::shared_ptr<IStreamIn>& stream, const sp<MicrophoneInfoProvider>& micInfoProvider)
+        : StreamHalAidl("StreamInHalAidl", true /*isInput*/, config, nominalLatency,
+                std::move(context), getStreamCommon(stream)),
+          mStream(stream), mMicInfoProvider(micInfoProvider) {}
+
+status_t StreamInHalAidl::setGain(float gain __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamInHalAidl::read(void *buffer, size_t bytes, size_t *read) {
+    if (buffer == nullptr || read == nullptr) {
+        return BAD_VALUE;
+    }
+    return transfer(buffer, bytes, read);
+}
+
+status_t StreamInHalAidl::getInputFramesLost(uint32_t *framesLost) {
+    if (framesLost == nullptr) {
+        return BAD_VALUE;
+    }
+    int32_t aidlXruns = 0;
+    if (status_t status = getXruns(&aidlXruns); status != OK) {
+        return status;
+    }
+    *framesLost = std::max<int32_t>(0, aidlXruns);
+    return OK;
+}
+
+status_t StreamInHalAidl::getCapturePosition(int64_t *frames, int64_t *time) {
+    if (frames == nullptr || time == nullptr) {
+        return BAD_VALUE;
+    }
+    return getObservablePosition(frames, time);
+}
+
+status_t StreamInHalAidl::getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) {
+    if (!microphones) {
+        return BAD_VALUE;
+    }
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    sp<MicrophoneInfoProvider> micInfoProvider = mMicInfoProvider.promote();
+    if (!micInfoProvider) return NO_INIT;
+    auto staticInfo = micInfoProvider->getMicrophoneInfo();
+    if (!staticInfo) return INVALID_OPERATION;
+    std::vector<MicrophoneDynamicInfo> dynamicInfo;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mStream->getActiveMicrophones(&dynamicInfo)));
+    std::vector<media::MicrophoneInfoFw> result;
+    result.reserve(dynamicInfo.size());
+    for (const auto& d : dynamicInfo) {
+        const auto staticInfoIt = std::find_if(staticInfo->begin(), staticInfo->end(),
+                [&](const auto& s) { return s.id == d.id; });
+        if (staticInfoIt != staticInfo->end()) {
+            // Convert into the c++ backend type from the ndk backend type via the legacy structure.
+            audio_microphone_characteristic_t legacy = VALUE_OR_RETURN_STATUS(
+                    ::aidl::android::aidl2legacy_MicrophoneInfos_audio_microphone_characteristic_t(
+                            *staticInfoIt, d));
+            media::MicrophoneInfoFw info = VALUE_OR_RETURN_STATUS(
+                    ::android::legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(
+                            legacy));
+            // 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());
+        }
+    }
+    *microphones = std::move(result);
+    return OK;
+}
+
+status_t StreamInHalAidl::updateSinkMetadata(
+        const StreamInHalInterface::SinkMetadata& sinkMetadata) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ::aidl::android::hardware::audio::common::SinkMetadata aidlMetadata =
+              VALUE_OR_RETURN_STATUS(legacy2aidl_SinkMetadata(sinkMetadata));
+    return statusTFromBinderStatus(mStream->updateMetadata(aidlMetadata));
+}
+
+status_t StreamInHalAidl::setPreferredMicrophoneDirection(
+            audio_microphone_direction_t direction __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+status_t StreamInHalAidl::setPreferredMicrophoneFieldDimension(float zoom __unused) {
+    TIME_CHECK();
+    if (!mStream) return NO_INIT;
+    ALOGE("%s not implemented yet", __func__);
+    return OK;
+}
+
+} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalAidl.h b/media/libaudiohal/impl/StreamHalAidl.h
new file mode 100644
index 0000000..157e8bb
--- /dev/null
+++ b/media/libaudiohal/impl/StreamHalAidl.h
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <string_view>
+
+#include <aidl/android/hardware/audio/common/AudioOffloadMetadata.h>
+#include <aidl/android/hardware/audio/core/BpStreamCommon.h>
+#include <aidl/android/hardware/audio/core/BpStreamIn.h>
+#include <aidl/android/hardware/audio/core/BpStreamOut.h>
+#include <fmq/AidlMessageQueue.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <media/AudioParameter.h>
+
+#include "ConversionHelperAidl.h"
+#include "StreamPowerLog.h"
+
+using ::aidl::android::hardware::audio::common::AudioOffloadMetadata;
+
+namespace android {
+
+class StreamContextAidl {
+  public:
+    typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Command,
+          ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> CommandMQ;
+    typedef AidlMessageQueue<::aidl::android::hardware::audio::core::StreamDescriptor::Reply,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> ReplyMQ;
+    typedef AidlMessageQueue<int8_t,
+            ::aidl::android::hardware::common::fmq::SynchronizedReadWrite> DataMQ;
+
+    explicit StreamContextAidl(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor,
+            bool isAsynchronous)
+        : mFrameSizeBytes(descriptor.frameSizeBytes),
+          mCommandMQ(new CommandMQ(descriptor.command)),
+          mReplyMQ(new ReplyMQ(descriptor.reply)),
+          mBufferSizeFrames(descriptor.bufferSizeFrames),
+          mDataMQ(maybeCreateDataMQ(descriptor)),
+          mIsAsynchronous(isAsynchronous) {}
+    StreamContextAidl(StreamContextAidl&& other) :
+            mFrameSizeBytes(other.mFrameSizeBytes),
+            mCommandMQ(std::move(other.mCommandMQ)),
+            mReplyMQ(std::move(other.mReplyMQ)),
+            mBufferSizeFrames(other.mBufferSizeFrames),
+            mDataMQ(std::move(other.mDataMQ)),
+            mIsAsynchronous(other.mIsAsynchronous) {}
+    StreamContextAidl& operator=(StreamContextAidl&& other) {
+        mFrameSizeBytes = other.mFrameSizeBytes;
+        mCommandMQ = std::move(other.mCommandMQ);
+        mReplyMQ = std::move(other.mReplyMQ);
+        mBufferSizeFrames = other.mBufferSizeFrames;
+        mDataMQ = std::move(other.mDataMQ);
+        mIsAsynchronous = other.mIsAsynchronous;
+        return *this;
+    }
+    bool isValid() const {
+        return mFrameSizeBytes != 0 &&
+                mCommandMQ != nullptr && mCommandMQ->isValid() &&
+                mReplyMQ != nullptr && mReplyMQ->isValid() &&
+                (mDataMQ != nullptr || (
+                        mDataMQ->isValid() &&
+                        mDataMQ->getQuantumCount() * mDataMQ->getQuantumSize() >=
+                        mFrameSizeBytes * mBufferSizeFrames));
+    }
+    size_t getBufferSizeBytes() const { return mFrameSizeBytes * mBufferSizeFrames; }
+    size_t getBufferSizeFrames() const { return mBufferSizeFrames; }
+    CommandMQ* getCommandMQ() const { return mCommandMQ.get(); }
+    DataMQ* getDataMQ() const { return mDataMQ.get(); }
+    size_t getFrameSizeBytes() const { return mFrameSizeBytes; }
+    ReplyMQ* getReplyMQ() const { return mReplyMQ.get(); }
+    bool isAsynchronous() const { return mIsAsynchronous; }
+
+  private:
+    static std::unique_ptr<DataMQ> maybeCreateDataMQ(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor& descriptor) {
+        using Tag = ::aidl::android::hardware::audio::core::StreamDescriptor::AudioBuffer::Tag;
+        if (descriptor.audio.getTag() == Tag::fmq) {
+            return std::make_unique<DataMQ>(descriptor.audio.get<Tag::fmq>());
+        }
+        return nullptr;
+    }
+
+    size_t mFrameSizeBytes;
+    std::unique_ptr<CommandMQ> mCommandMQ;
+    std::unique_ptr<ReplyMQ> mReplyMQ;
+    size_t mBufferSizeFrames;
+    std::unique_ptr<DataMQ> mDataMQ;
+    bool mIsAsynchronous;
+};
+
+class StreamHalAidl : public virtual StreamHalInterface, public ConversionHelperAidl {
+  public:
+    // Return size of input/output buffer in bytes for this stream - eg. 4800.
+    status_t getBufferSize(size_t *size) override;
+
+    // Return the base configuration of the stream:
+    //   - channel mask;
+    //   - format - e.g. AUDIO_FORMAT_PCM_16_BIT;
+    //   - sampling rate in Hz - eg. 44100.
+    status_t getAudioProperties(audio_config_base_t *configBase) override;
+
+    // Set audio stream parameters.
+    status_t setParameters(const String8& kvPairs) override;
+
+    // Get audio stream parameters.
+    status_t getParameters(const String8& keys, String8 *values) override;
+
+    // Return the frame size (number of bytes per sample) of a stream.
+    status_t getFrameSize(size_t *size) override;
+
+    // Add or remove the effect on the stream.
+    status_t addEffect(sp<EffectHalInterface> effect) override;
+    status_t removeEffect(sp<EffectHalInterface> effect) override;
+
+    // Put the audio hardware input/output into standby mode.
+    status_t standby() override;
+
+    status_t dump(int fd, const Vector<String16>& args) override;
+
+    // Start a stream operating in mmap mode.
+    status_t start() override;
+
+    // Stop a stream operating in mmap mode.
+    status_t stop() override;
+
+    // Retrieve information on the data buffer in mmap mode.
+    status_t createMmapBuffer(int32_t minSizeFrames,
+            struct audio_mmap_buffer_info *info) override;
+
+    // Get current read/write position in the mmap buffer
+    status_t getMmapPosition(struct audio_mmap_position *position) override;
+
+    // Set the priority of the thread that interacts with the HAL
+    // (must match the priority of the audioflinger's thread that calls 'read' / 'write')
+    status_t setHalThreadPriority(int priority) override;
+
+    status_t legacyCreateAudioPatch(const struct audio_port_config& port,
+            std::optional<audio_source_t> source,
+            audio_devices_t type) override;
+
+    status_t legacyReleaseAudioPatch() override;
+
+  protected:
+    template<class T>
+    static std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> getStreamCommon(
+            const std::shared_ptr<T>& stream);
+
+    // Subclasses can not be constructed directly by clients.
+    StreamHalAidl(std::string_view className,
+            bool isInput,
+            const audio_config& config,
+            int32_t nominalLatency,
+            StreamContextAidl&& context,
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon>& stream);
+
+    ~StreamHalAidl() override;
+
+    status_t getHalPid(pid_t *pid);
+
+    bool requestHalThreadPriority(pid_t threadPid, pid_t threadId);
+
+    status_t getLatency(uint32_t *latency);
+
+    status_t getObservablePosition(int64_t *frames, int64_t *timestamp);
+
+    status_t getXruns(int32_t *frames);
+
+    status_t transfer(void *buffer, size_t bytes, size_t *transferred);
+
+    status_t pause(
+            ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+    status_t resume(
+            ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+    status_t drain(bool earlyNotify,
+            ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+    status_t flush(
+            ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+    status_t exit();
+
+    const bool mIsInput;
+    const audio_config_base_t mConfig;
+    const StreamContextAidl mContext;
+
+  private:
+    static audio_config_base_t configToBase(const audio_config& config) {
+        audio_config_base_t result = AUDIO_CONFIG_BASE_INITIALIZER;
+        result.sample_rate = config.sample_rate;
+        result.channel_mask = config.channel_mask;
+        result.format = config.format;
+        return result;
+    }
+    ::aidl::android::hardware::audio::core::StreamDescriptor::State getState() {
+        std::lock_guard l(mLock);
+        return mLastReply.state;
+    }
+    status_t sendCommand(
+            const ::aidl::android::hardware::audio::core::StreamDescriptor::Command &command,
+            ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr,
+            bool safeFromNonWorkerThread = false);
+    status_t updateCountersIfNeeded(
+            ::aidl::android::hardware::audio::core::StreamDescriptor::Reply* reply = nullptr);
+
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamCommon> mStream;
+    std::mutex mLock;
+    ::aidl::android::hardware::audio::core::StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
+    // mStreamPowerLog is used for audio signal power logging.
+    StreamPowerLog mStreamPowerLog;
+    std::atomic<pid_t> mWorkerTid = -1;
+};
+
+class CallbackBroker;
+
+class StreamOutHalAidl : public StreamOutHalInterface, public StreamHalAidl {
+  public:
+    // Extract the output stream parameters and set by AIDL APIs.
+    status_t setParameters(const String8& kvPairs) override;
+
+    // Return the audio hardware driver estimated latency in milliseconds.
+    status_t getLatency(uint32_t *latency) override;
+
+    // Use this method in situations where audio mixing is done in the hardware.
+    status_t setVolume(float left, float right) override;
+
+    // Selects the audio presentation (if available).
+    status_t selectPresentation(int presentationId, int programId) override;
+
+    // Write audio buffer to driver.
+    status_t write(const void *buffer, size_t bytes, size_t *written) override;
+
+    // Return the number of audio frames written by the audio dsp to DAC since
+    // the output has exited standby.
+    status_t getRenderPosition(uint32_t *dspFrames) override;
+
+    // Get the local time at which the next write to the audio driver will be presented.
+    status_t getNextWriteTimestamp(int64_t *timestamp) override;
+
+    // Set the callback for notifying completion of non-blocking write and drain.
+    status_t setCallback(wp<StreamOutHalInterfaceCallback> callback) override;
+
+    // Returns whether pause and resume operations are supported.
+    status_t supportsPauseAndResume(bool *supportsPause, bool *supportsResume) override;
+
+    // Notifies to the audio driver to resume playback following a pause.
+    status_t pause() override;
+
+    // Notifies to the audio driver to resume playback following a pause.
+    status_t resume() override;
+
+    // Returns whether drain operation is supported.
+    status_t supportsDrain(bool *supportsDrain) override;
+
+    // Requests notification when data buffered by the driver/hardware has been played.
+    status_t drain(bool earlyNotify) override;
+
+    // Notifies to the audio driver to flush the queued data.
+    status_t flush() override;
+
+    // Return a recent count of the number of audio frames presented to an external observer.
+    status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) override;
+
+    // Called when the metadata of the stream's source has been changed.
+    status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
+
+    // Returns the Dual Mono mode presentation setting.
+    status_t getDualMonoMode(audio_dual_mono_mode_t* mode) override;
+
+    // Sets the Dual Mono mode presentation on the output device.
+    status_t setDualMonoMode(audio_dual_mono_mode_t mode) override;
+
+    // Returns the Audio Description Mix level in dB.
+    status_t getAudioDescriptionMixLevel(float* leveldB) override;
+
+    // Sets the Audio Description Mix level in dB.
+    status_t setAudioDescriptionMixLevel(float leveldB) override;
+
+    // Retrieves current playback rate parameters.
+    status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) override;
+
+    // Sets the playback rate parameters that control playback behavior.
+    status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) override;
+
+    status_t setEventCallback(const sp<StreamOutHalInterfaceEventCallback>& callback) override;
+
+    status_t setLatencyMode(audio_latency_mode_t mode) override;
+    status_t getRecommendedLatencyModes(std::vector<audio_latency_mode_t> *modes) override;
+    status_t setLatencyModeCallback(
+            const sp<StreamOutHalInterfaceLatencyModeCallback>& callback) override;
+
+    status_t exit() override;
+
+  private:
+    friend class sp<StreamOutHalAidl>;
+
+    static ConversionResult<::aidl::android::hardware::audio::common::SourceMetadata>
+    legacy2aidl_SourceMetadata(const StreamOutHalInterface::SourceMetadata& legacy);
+
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut> mStream;
+    const wp<CallbackBroker> mCallbackBroker;
+
+    AudioOffloadMetadata mOffloadMetadata;
+
+    // Can not be constructed directly by clients.
+    StreamOutHalAidl(
+            const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamOut>& stream,
+            const sp<CallbackBroker>& callbackBroker);
+
+    ~StreamOutHalAidl() override;
+
+    // Filter and update the offload metadata. The parameters which are related to the offload
+    // metadata will be removed after filtering.
+    status_t filterAndUpdateOffloadMetadata(AudioParameter &parameters);
+};
+
+class MicrophoneInfoProvider;
+
+class StreamInHalAidl : public StreamInHalInterface, public StreamHalAidl {
+  public:
+    // Set the input gain for the audio driver.
+    status_t setGain(float gain) override;
+
+    // Read audio buffer in from driver.
+    status_t read(void *buffer, size_t bytes, size_t *read) override;
+
+    // Return the amount of input frames lost in the audio driver.
+    status_t getInputFramesLost(uint32_t *framesLost) override;
+
+    // Return a recent count of the number of audio frames received and
+    // the clock time associated with that frame count.
+    status_t getCapturePosition(int64_t *frames, int64_t *time) override;
+
+    // Get active microphones
+    status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override;
+
+    // Set microphone direction (for processing)
+    status_t setPreferredMicrophoneDirection(
+                            audio_microphone_direction_t direction) override;
+
+    // Set microphone zoom (for processing)
+    status_t setPreferredMicrophoneFieldDimension(float zoom) override;
+
+    // Called when the metadata of the stream's sink has been changed.
+    status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
+
+  private:
+    friend class sp<StreamInHalAidl>;
+
+    static ConversionResult<::aidl::android::hardware::audio::common::SinkMetadata>
+    legacy2aidl_SinkMetadata(const StreamInHalInterface::SinkMetadata& legacy);
+
+    const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn> mStream;
+    const wp<MicrophoneInfoProvider> mMicInfoProvider;
+
+    // Can not be constructed directly by clients.
+    StreamInHalAidl(
+            const audio_config& config, StreamContextAidl&& context, int32_t nominalLatency,
+            const std::shared_ptr<::aidl::android::hardware::audio::core::IStreamIn>& stream,
+            const sp<MicrophoneInfoProvider>& micInfoProvider);
+
+    ~StreamInHalAidl() override = default;
+};
+
+} // namespace android
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 76f9a60..192790c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -24,6 +24,9 @@
 #include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/TimeCheck.h>
 #include <utils/Log.h>
+#if MAJOR_VERSION >= 4
+#include <media/AidlConversion.h>
+#endif
 
 #include PATH(android/hardware/audio/CORE_TYPES_FILE_VERSION/IStreamOutCallback.h)
 #include <HidlUtils.h>
@@ -46,9 +49,6 @@
 using namespace ::android::hardware::audio::common::COMMON_TYPES_CPP_VERSION;
 using namespace ::android::hardware::audio::CORE_TYPES_CPP_VERSION;
 
-#define TIME_CHECK() auto TimeCheck = \
-       mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
-
 StreamHalHidl::StreamHalHidl(std::string_view className, IStream *stream)
         : CoreConversionHelperHidl(className),
           mStream(stream),
@@ -441,7 +441,7 @@
 #endif
 
 status_t StreamOutHalHidl::write(const void *buffer, size_t bytes, size_t *written) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     *written = 0;
 
@@ -587,7 +587,7 @@
 }
 
 status_t StreamOutHalHidl::getRenderPosition(uint32_t *dspFrames) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     Result retval;
     Return<void> ret = mStream->getRenderPosition(
@@ -668,7 +668,7 @@
 }
 
 status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct timespec *timestamp) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     if (mWriterClient == gettid() && mCommandMQ) {
         return callWriterThread(
@@ -1012,7 +1012,7 @@
 }
 
 status_t StreamInHalHidl::read(void *buffer, size_t bytes, size_t *read) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     *read = 0;
 
@@ -1146,7 +1146,7 @@
 }
 
 status_t StreamInHalHidl::getCapturePosition(int64_t *frames, int64_t *time) {
-    // TIME_CHECK();  // TODO(b/238654698) reenable only when optimized.
+    // TIME_CHECK();  // TODO(b/243839867) reenable only when optimized.
     if (mStream == 0) return NO_INIT;
     if (mReaderClient == gettid() && mCommandMQ) {
         ReadParameters params;
@@ -1172,7 +1172,7 @@
 
 #if MAJOR_VERSION == 2
 status_t StreamInHalHidl::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo> *microphones __unused) {
+        std::vector<media::MicrophoneInfoFw> *microphones __unused) {
     if (mStream == 0) return NO_INIT;
     return INVALID_OPERATION;
 }
@@ -1185,7 +1185,7 @@
 
 #elif MAJOR_VERSION >= 4
 status_t StreamInHalHidl::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo> *microphonesInfo) {
+        std::vector<media::MicrophoneInfoFw> *microphonesInfo) {
     TIME_CHECK();
     if (!mStream) return NO_INIT;
     Result retval;
@@ -1193,11 +1193,17 @@
             [&](Result r, hidl_vec<MicrophoneInfo> micArrayHal) {
         retval = r;
         for (size_t k = 0; k < micArrayHal.size(); k++) {
+            // Convert via legacy.
             audio_microphone_characteristic_t dst;
-            // convert
             (void)CoreUtils::microphoneInfoToHal(micArrayHal[k], &dst);
-            media::MicrophoneInfo microphone = media::MicrophoneInfo(dst);
-            microphonesInfo->push_back(microphone);
+            auto conv = legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(dst);
+            if (conv.ok()) {
+                microphonesInfo->push_back(conv.value());
+            } else {
+                ALOGW("getActiveMicrophones: could not convert %s to AIDL: %d",
+                        toString(micArrayHal[k]).c_str(), conv.error());
+                microphonesInfo->push_back(media::MicrophoneInfoFw{});
+            }
         }
     });
     return processReturn("getActiveMicrophones", ret, retval);
diff --git a/media/libaudiohal/impl/StreamHalHidl.h b/media/libaudiohal/impl/StreamHalHidl.h
index 54fbefe..5361047 100644
--- a/media/libaudiohal/impl/StreamHalHidl.h
+++ b/media/libaudiohal/impl/StreamHalHidl.h
@@ -253,7 +253,7 @@
     virtual status_t getCapturePosition(int64_t *frames, int64_t *time);
 
     // Get active microphones
-    virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+    status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) override;
 
     // Set microphone direction (for processing)
     virtual status_t setPreferredMicrophoneDirection(
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
new file mode 100644
index 0000000..92b77d8
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAec"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_aec.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAec.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AcousticEchoCanceler;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAec::setParameter(EffectParamReader& param) {
+    uint32_t type, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&type) ||
+        OK != param.readFromValue(&value)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    Parameter aidlParam;
+    switch (type) {
+        case AEC_PARAM_ECHO_DELAY:
+            FALLTHROUGH_INTENDED;
+        case AEC_PARAM_PROPERTIES: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_uint32_echoDelay_Parameter_aec(value));
+            break;
+        }
+        case AEC_PARAM_MOBILE_MODE: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_uint32_mobileMode_Parameter_aec(value));
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(AcousticEchoCanceler, acousticEchoCanceler, vendor,
+                                                ext);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam)));
+            break;
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAec::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&type)) {
+        param.setStatus(BAD_VALUE);
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case AEC_PARAM_ECHO_DELAY:
+            FALLTHROUGH_INTENDED;
+        case AEC_PARAM_PROPERTIES: {
+            int32_t delay = 0;
+            Parameter::Id id =
+                    MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler, acousticEchoCancelerTag,
+                                               AcousticEchoCanceler::echoDelayUs);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            delay = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_aec_uint32_echoDelay(aidlParam));
+            return param.writeToValue(&delay);
+        }
+        case AEC_PARAM_MOBILE_MODE: {
+            int32_t mode = 0;
+            Parameter::Id id =
+                    MAKE_SPECIFIC_PARAMETER_ID(AcousticEchoCanceler, acousticEchoCancelerTag,
+                                               AcousticEchoCanceler::mobileMode);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            mode = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_aec_uint32_mobileMode(aidlParam));
+            return param.writeToValue(&mode);
+        }
+        default: {
+            // use vendor extension implementation, the first 32bits (param type) won't pass to HAL
+            VENDOR_EXTENSION_GET_AND_RETURN(AcousticEchoCanceler, acousticEchoCanceler, param);
+        }
+    }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
new file mode 100644
index 0000000..3ee419a
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAec.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAec : public EffectConversionHelperAidl {
+  public:
+    AidlConversionAec(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+                      int32_t sessionId, int32_t ioId,
+                      const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionAec() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp
new file mode 100644
index 0000000..1363ba4
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAgc1"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_agc.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAgc1.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV1;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAgc1::setParameterLevel(EffectParamReader& param) {
+    int16_t level;
+    RETURN_STATUS_IF_ERROR(param.readFromValue(&level));
+    Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1,
+                                                  targetPeakLevelDbFs, level);
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc1::setParameterGain(EffectParamReader& param) {
+    int16_t gain;
+    RETURN_STATUS_IF_ERROR(param.readFromValue(&gain));
+    Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1,
+                                                  maxCompressionGainDb, gain);
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc1::setParameterLimiterEnable(EffectParamReader& param) {
+    bool enable;
+    RETURN_STATUS_IF_ERROR(param.readFromValue(&enable));
+    Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1, automaticGainControlV1,
+                                                  enableLimiter, enable);
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc1::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    if (OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    switch (type) {
+        case AGC_PARAM_TARGET_LEVEL: {
+            return setParameterLevel(param);
+        }
+        case AGC_PARAM_COMP_GAIN: {
+            return setParameterGain(param);
+        }
+        case AGC_PARAM_LIMITER_ENA: {
+            return setParameterLimiterEnable(param);
+        }
+        case AGC_PARAM_PROPERTIES: {
+            RETURN_STATUS_IF_ERROR(setParameterLevel(param));
+            RETURN_STATUS_IF_ERROR(setParameterGain(param));
+            RETURN_STATUS_IF_ERROR(setParameterLimiterEnable(param));
+            return OK;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV1,
+                                                          automaticGainControlV1, vendor, ext);
+            return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+        }
+    }
+}
+
+status_t AidlConversionAgc1::getParameterLevel(EffectParamWriter& param) {
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV1, automaticGainControlV1Tag,
+                                                  AutomaticGainControlV1::targetPeakLevelDbFs);
+    Parameter aidlParam;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    int32_t level = VALUE_OR_RETURN_STATUS(
+            GET_PARAMETER_SPECIFIC_FIELD(aidlParam, AutomaticGainControlV1, automaticGainControlV1,
+                                         AutomaticGainControlV1::targetPeakLevelDbFs, int32_t));
+    return param.writeToValue(&level);
+}
+
+status_t AidlConversionAgc1::getParameterGain(EffectParamWriter& param) {
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV1, automaticGainControlV1Tag,
+                                                  AutomaticGainControlV1::maxCompressionGainDb);
+    Parameter aidlParam;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    int32_t gain = VALUE_OR_RETURN_STATUS(
+            GET_PARAMETER_SPECIFIC_FIELD(aidlParam, AutomaticGainControlV1, automaticGainControlV1,
+                                         AutomaticGainControlV1::maxCompressionGainDb, int32_t));
+    return param.writeToValue(&gain);
+}
+
+status_t AidlConversionAgc1::getParameterLimiterEnable(EffectParamWriter& param) {
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV1, automaticGainControlV1Tag,
+                                                  AutomaticGainControlV1::enableLimiter);
+    Parameter aidlParam;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    bool enable = VALUE_OR_RETURN_STATUS(
+            GET_PARAMETER_SPECIFIC_FIELD(aidlParam, AutomaticGainControlV1, automaticGainControlV1,
+                                         AutomaticGainControlV1::enableLimiter, bool));
+    return param.writeToValue(&enable);
+}
+
+status_t AidlConversionAgc1::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    switch (type) {
+        case AGC_PARAM_TARGET_LEVEL: {
+            return getParameterLevel(param);
+        }
+        case AGC_PARAM_COMP_GAIN: {
+            return getParameterGain(param);
+        }
+        case AGC_PARAM_LIMITER_ENA: {
+            return getParameterLimiterEnable(param);
+        }
+        case AGC_PARAM_PROPERTIES: {
+            RETURN_STATUS_IF_ERROR(getParameterLevel(param));
+            RETURN_STATUS_IF_ERROR(getParameterGain(param));
+            RETURN_STATUS_IF_ERROR(getParameterLimiterEnable(param));
+            return OK;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(AutomaticGainControlV1, automaticGainControlV1, param);
+        }
+    }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
new file mode 100644
index 0000000..b0509fd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc1.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAgc1 : public EffectConversionHelperAidl {
+  public:
+    AidlConversionAgc1(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+                       int32_t sessionId, int32_t ioId,
+                       const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionAgc1() {}
+
+  private:
+    status_t setParameterLevel(utils::EffectParamReader& param);
+    status_t setParameterGain(utils::EffectParamReader& param);
+    status_t setParameterLimiterEnable(utils::EffectParamReader& param);
+    status_t setParameter(utils::EffectParamReader& param) override;
+
+    status_t getParameterLevel(utils::EffectParamWriter& param);
+    status_t getParameterGain(utils::EffectParamWriter& param);
+    status_t getParameterLimiterEnable(utils::EffectParamWriter& param);
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
new file mode 100644
index 0000000..b35a1c6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionAgc2"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_agc2.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionAgc2.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::AutomaticGainControlV2;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionAgc2::setParameter(EffectParamReader& param) {
+    uint32_t type = 0, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_uint32_fixedDigitalGain_Parameter_agc(value));
+            break;
+        }
+        case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_uint32_levelEstimator_Parameter_agc(value));
+            break;
+        }
+        case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_uint32_saturationMargin_Parameter_agc(value));
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(AutomaticGainControlV2, automaticGainControlV2,
+                                                vendor, ext);
+            break;
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionAgc2::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case AGC2_PARAM_FIXED_DIGITAL_GAIN: {
+            Parameter::Id id =
+                    MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+                                               AutomaticGainControlV2::fixedDigitalGainMb);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_agc_uint32_fixedDigitalGain(aidlParam));
+            break;
+        }
+        case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR: {
+            Parameter::Id id =
+                    MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+                                               AutomaticGainControlV2::levelEstimator);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_agc_uint32_levelEstimator(aidlParam));
+            break;
+        }
+        case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN: {
+            Parameter::Id id =
+                    MAKE_SPECIFIC_PARAMETER_ID(AutomaticGainControlV2, automaticGainControlV2Tag,
+                                               AutomaticGainControlV2::saturationMarginMb);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_agc_uint32_saturationMargin(aidlParam));
+            break;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(AutomaticGainControlV2, automaticGainControlV2, param);
+        }
+    }
+
+    return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
new file mode 100644
index 0000000..8f7eac7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionAgc2.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionAgc2 : public EffectConversionHelperAidl {
+  public:
+    AidlConversionAgc2(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+                       int32_t sessionId, int32_t ioId,
+                       const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionAgc2() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
new file mode 100644
index 0000000..7c6a5a2
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionBassBoost"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
+#include <system/audio_effects/effect_bassboost.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionBassBoost.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::BassBoost;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionBassBoost::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    uint16_t value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case BASSBOOST_PARAM_STRENGTH: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_uint16_strengthPm_Parameter_BassBoost(value));
+            break;
+        }
+        case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
+            ALOGW("%s set BASSBOOST_PARAM_STRENGTH_SUPPORTED not supported", __func__);
+            return BAD_VALUE;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(BassBoost, bassBoost, vendor, ext);
+            break;
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionBassBoost::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case BASSBOOST_PARAM_STRENGTH: {
+            uint16_t value;
+            Parameter::Id id =
+                    MAKE_SPECIFIC_PARAMETER_ID(BassBoost, bassBoostTag, BassBoost::strengthPm);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_BassBoost_uint16_strengthPm(aidlParam));
+            return param.writeToValue(&value);
+        }
+        case BASSBOOST_PARAM_STRENGTH_SUPPORTED: {
+            // an invalid range indicates not setting support for this parameter
+            uint32_t value =
+                    ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::bassBoost>(
+                            BassBoost::strengthPm, mDesc.capability);
+            return param.writeToValue(&value);
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(BassBoost, bassBoost, param);
+        }
+    }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
new file mode 100644
index 0000000..9664aa1
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionBassBoost.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionBassBoost : public EffectConversionHelperAidl {
+  public:
+    AidlConversionBassBoost(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionBassBoost() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp
new file mode 100644
index 0000000..b57971c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionDownmix"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_downmix.h>
+
+#include <system/audio_effect.h>
+#include <utils/Log.h>
+
+#include "AidlConversionDownmix.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Downmix;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionDownmix::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    int16_t value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int16_t)) ||
+        OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case DOWNMIX_PARAM_TYPE: {
+            aidlParam = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_int16_type_Parameter_Downmix(value));
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Downmix, downmix, vendor, ext);
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionDownmix::getParameter(EffectParamWriter& param) {
+    int16_t value = 0;
+    uint32_t type = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type)) {
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case DOWNMIX_PARAM_TYPE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Downmix, downmixTag, Downmix::type);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_Downmix_int16_type(aidlParam));
+            break;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(Downmix, downmix, param);
+        }
+    }
+
+    return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
new file mode 100644
index 0000000..8b28ca3
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDownmix.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BpEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionDownmix : public EffectConversionHelperAidl {
+  public:
+    AidlConversionDownmix(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+                          int32_t sessionId, int32_t ioId,
+                          const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionDownmix() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
new file mode 100644
index 0000000..fe845ab
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionDp"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effect.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
+#include <Utils.h>
+#include <utils/Log.h>
+
+#include "AidlConversionDynamicsProcessing.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Capability;
+using ::aidl::android::hardware::audio::effect::DynamicsProcessing;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::toString;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionDp::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&type));
+    Parameter aidlParam;
+    switch (type) {
+        case DP_PARAM_INPUT_GAIN: {
+            DynamicsProcessing::InputGain inputGainAidl;
+            RETURN_STATUS_IF_ERROR(param.readFromParameter(&inputGainAidl.channel));
+            RETURN_STATUS_IF_ERROR(param.readFromValue(&inputGainAidl.gainDb));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, inputGain,
+                                                {inputGainAidl});
+            break;
+        }
+        case DP_PARAM_ENGINE_ARCHITECTURE: {
+            DynamicsProcessing::EngineArchitecture engine =
+                    VALUE_OR_RETURN_STATUS(readEngineArchitectureFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing,
+                                                engineArchitecture, engine);
+            mEngine = engine;
+            break;
+        }
+        case DP_PARAM_PRE_EQ: {
+            DynamicsProcessing::ChannelConfig chConfig =
+                    VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEq,
+                                                {chConfig});
+            break;
+        }
+        case DP_PARAM_POST_EQ: {
+            DynamicsProcessing::ChannelConfig chConfig =
+                    VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEq,
+                                                {chConfig});
+            break;
+        }
+        case DP_PARAM_MBC: {
+            DynamicsProcessing::ChannelConfig chConfig =
+                    VALUE_OR_RETURN_STATUS(readChannelConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbc,
+                                                {chConfig});
+            break;
+        }
+        case DP_PARAM_PRE_EQ_BAND: {
+            DynamicsProcessing::EqBandConfig bandConfig =
+                    VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, preEqBand,
+                                                {bandConfig});
+            break;
+        }
+        case DP_PARAM_POST_EQ_BAND: {
+            DynamicsProcessing::EqBandConfig bandConfig =
+                    VALUE_OR_RETURN_STATUS(readEqBandConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, postEqBand,
+                                                {bandConfig});
+            break;
+        }
+        case DP_PARAM_MBC_BAND: {
+            DynamicsProcessing::MbcBandConfig bandConfig =
+                    VALUE_OR_RETURN_STATUS(readMbcBandConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, mbcBand,
+                                                {bandConfig});
+            break;
+        }
+        case DP_PARAM_LIMITER: {
+            DynamicsProcessing::LimiterConfig config =
+                    VALUE_OR_RETURN_STATUS(readLimiterConfigFromParam(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, limiter,
+                                                {config});
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam =
+                    MAKE_SPECIFIC_PARAMETER(DynamicsProcessing, dynamicsProcessing, vendor, ext);
+            break;
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionDp::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&type));
+    Parameter aidlParam;
+    switch (type) {
+        case DP_PARAM_INPUT_GAIN: {
+            int32_t channel;
+            RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+                                                          DynamicsProcessing::inputGain);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+            std::vector<DynamicsProcessing::InputGain> gains =
+                    VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                            aidlParam, DynamicsProcessing, dynamicsProcessing,
+                            DynamicsProcessing::inputGain,
+                            std::vector<DynamicsProcessing::InputGain>));
+            for (const auto& gain : gains) {
+                if (gain.channel == channel) {
+                    return param.writeToValue(&gain.gainDb);
+                }
+            }
+            ALOGE("%s not able to find channel %d", __func__, channel);
+            return BAD_VALUE;
+        }
+        case DP_PARAM_ENGINE_ARCHITECTURE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+                                                          DynamicsProcessing::engineArchitecture);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+            DynamicsProcessing::EngineArchitecture engine =
+                    VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                            aidlParam, DynamicsProcessing, dynamicsProcessing,
+                            DynamicsProcessing::engineArchitecture,
+                            DynamicsProcessing::EngineArchitecture));
+            int32_t resolution = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_DynamicsProcessing_ResolutionPreference_int32(
+                            engine.resolutionPreference));
+            int32_t preEqInUse =
+                    VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.preEqStage.inUse));
+            int32_t mbcInUse =
+                    VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.mbcStage.inUse));
+            int32_t postEqInUse =
+                    VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.postEqStage.inUse));
+            int32_t limiterInUse =
+                    VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(engine.limiterInUse));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&resolution));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.preferredProcessingDurationMs));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&preEqInUse));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.preEqStage.bandCount));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&mbcInUse));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.mbcStage.bandCount));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&postEqInUse));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&engine.postEqStage.bandCount));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&limiterInUse));
+            mEngine = engine;
+            return OK;
+        }
+        case DP_PARAM_PRE_EQ: {
+            return getChannelConfig(DynamicsProcessing::preEq, param);
+        }
+        case DP_PARAM_POST_EQ: {
+            return getChannelConfig(DynamicsProcessing::postEq, param);
+        }
+        case DP_PARAM_MBC: {
+            return getChannelConfig(DynamicsProcessing::mbc, param);
+        }
+        case DP_PARAM_PRE_EQ_BAND: {
+            return getEqBandConfig(DynamicsProcessing::preEqBand, param);
+        }
+        case DP_PARAM_POST_EQ_BAND: {
+            return getEqBandConfig(DynamicsProcessing::postEqBand, param);
+        }
+        case DP_PARAM_MBC_BAND: {
+            return getMbcBandConfig(param);
+        }
+        case DP_PARAM_LIMITER: {
+            return getLimiterConfig(param);
+        }
+        case DP_PARAM_GET_CHANNEL_COUNT: {
+            uint32_t channel = ::aidl::android::hardware::audio::common::getChannelCount(
+                    mCommon.input.base.channelMask);
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&channel));
+            return OK;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(DynamicsProcessing, dynamicsProcessing, param);
+        }
+    }
+}
+
+ConversionResult<DynamicsProcessing::ChannelConfig>
+AidlConversionDp::readChannelConfigFromParam(EffectParamReader& param) {
+    int32_t enable, channel;
+    RETURN_IF_ERROR(param.readFromParameter(&channel));
+    RETURN_IF_ERROR(param.readFromValue(&enable));
+
+    return DynamicsProcessing::ChannelConfig(
+            {.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable)), .channel = channel});
+}
+
+ConversionResult<DynamicsProcessing::EqBandConfig>
+AidlConversionDp::readEqBandConfigFromParam(EffectParamReader& param) {
+    DynamicsProcessing::EqBandConfig config;
+    int32_t enable;
+    RETURN_IF_ERROR(param.readFromParameter(&config.channel));
+    RETURN_IF_ERROR(param.readFromParameter(&config.band));
+    RETURN_IF_ERROR(param.readFromValue(&enable));
+    RETURN_IF_ERROR(param.readFromValue(&config.cutoffFrequencyHz));
+    RETURN_IF_ERROR(param.readFromValue(&config.gainDb));
+
+    config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+    return config;
+}
+
+ConversionResult<DynamicsProcessing::MbcBandConfig>
+AidlConversionDp::readMbcBandConfigFromParam(EffectParamReader& param) {
+    DynamicsProcessing::MbcBandConfig config;
+    int32_t enable;
+    RETURN_IF_ERROR(param.readFromParameter(&config.channel));
+    RETURN_IF_ERROR(param.readFromParameter(&config.band));
+    RETURN_IF_ERROR(param.readFromValue(&enable));
+    RETURN_IF_ERROR(param.readFromValue(&config.cutoffFrequencyHz));
+    RETURN_IF_ERROR(param.readFromValue(&config.attackTimeMs));
+    RETURN_IF_ERROR(param.readFromValue(&config.releaseTimeMs));
+    RETURN_IF_ERROR(param.readFromValue(&config.ratio));
+    RETURN_IF_ERROR(param.readFromValue(&config.thresholdDb));
+    RETURN_IF_ERROR(param.readFromValue(&config.kneeWidthDb));
+    RETURN_IF_ERROR(param.readFromValue(&config.noiseGateThresholdDb));
+    RETURN_IF_ERROR(param.readFromValue(&config.expanderRatio));
+    RETURN_IF_ERROR(param.readFromValue(&config.preGainDb));
+    RETURN_IF_ERROR(param.readFromValue(&config.postGainDb));
+
+    config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+    return config;
+}
+
+ConversionResult<DynamicsProcessing::LimiterConfig>
+AidlConversionDp::readLimiterConfigFromParam(EffectParamReader& param) {
+    DynamicsProcessing::LimiterConfig config;
+    int32_t enable, inUse;
+    RETURN_IF_ERROR(param.readFromParameter(&config.channel));
+    RETURN_IF_ERROR(param.readFromValue(&inUse));
+    RETURN_IF_ERROR(param.readFromValue(&enable));
+    RETURN_IF_ERROR(param.readFromValue(&config.linkGroup));
+    RETURN_IF_ERROR(param.readFromValue(&config.attackTimeMs));
+    RETURN_IF_ERROR(param.readFromValue(&config.releaseTimeMs));
+    RETURN_IF_ERROR(param.readFromValue(&config.ratio));
+    RETURN_IF_ERROR(param.readFromValue(&config.thresholdDb));
+    RETURN_IF_ERROR(param.readFromValue(&config.postGainDb));
+
+    config.enable = VALUE_OR_RETURN(convertIntegral<bool>(enable));
+    return config;
+}
+
+ConversionResult<DynamicsProcessing::EngineArchitecture>
+AidlConversionDp::readEngineArchitectureFromParam(EffectParamReader& param) {
+    DynamicsProcessing::EngineArchitecture engine;
+    int32_t variant, preEqInUse, mbcInUse, postEqInUse, limiterInUse;
+    RETURN_IF_ERROR(param.readFromValue(&variant));
+    RETURN_IF_ERROR(param.readFromValue(&engine.preferredProcessingDurationMs));
+    RETURN_IF_ERROR(param.readFromValue(&preEqInUse));
+    RETURN_IF_ERROR(param.readFromValue(&engine.preEqStage.bandCount));
+    RETURN_IF_ERROR(param.readFromValue(&mbcInUse));
+    RETURN_IF_ERROR(param.readFromValue(&engine.mbcStage.bandCount));
+    RETURN_IF_ERROR(param.readFromValue(&postEqInUse));
+    RETURN_IF_ERROR(param.readFromValue(&engine.postEqStage.bandCount));
+    RETURN_IF_ERROR(param.readFromValue(&limiterInUse));
+
+    engine.resolutionPreference = VALUE_OR_RETURN(
+            aidl::android::legacy2aidl_int32_DynamicsProcessing_ResolutionPreference(variant));
+    engine.preEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(preEqInUse));
+    engine.mbcStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(mbcInUse));
+    engine.postEqStage.inUse = VALUE_OR_RETURN(convertIntegral<bool>(postEqInUse));
+    engine.limiterInUse = VALUE_OR_RETURN(convertIntegral<bool>(limiterInUse));
+    return engine;
+}
+
+status_t AidlConversionDp::getChannelConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
+    int32_t channel;
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+
+    Parameter aidlParam;
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+    std::vector<DynamicsProcessing::ChannelConfig> channels;
+    int32_t inUse, bandCount;
+    switch (tag) {
+        case DynamicsProcessing::preEq: {
+            inUse = mEngine.preEqStage.inUse;
+            bandCount = mEngine.preEqStage.bandCount;
+            channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::preEq,
+                    std::vector<DynamicsProcessing::ChannelConfig>));
+            break;
+        }
+        case DynamicsProcessing::postEq: {
+            inUse = mEngine.postEqStage.inUse;
+            bandCount = mEngine.postEqStage.bandCount;
+            channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::postEq,
+                    std::vector<DynamicsProcessing::ChannelConfig>));
+            break;
+        }
+        case DynamicsProcessing::mbc: {
+            inUse = mEngine.mbcStage.inUse;
+            bandCount = mEngine.mbcStage.bandCount;
+            channels = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, DynamicsProcessing, dynamicsProcessing, DynamicsProcessing::mbc,
+                    std::vector<DynamicsProcessing::ChannelConfig>));
+            break;
+        }
+        default: {
+            ALOGE("%s unsupported tag %s", __func__, toString(tag).c_str());
+            return BAD_VALUE;
+        }
+    }
+
+    for (const auto& ch : channels) {
+        if (ch.channel == channel) {
+            int32_t enable = ch.enable;
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&inUse));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandCount));
+            return OK;
+        }
+    }
+    ALOGE("%s not able to find channel %d", __func__, channel);
+    return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getEqBandConfig(DynamicsProcessing::Tag tag, EffectParamWriter& param) {
+    int32_t channel, band;
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&band));
+
+    Parameter aidlParam;
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag, tag);
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+    std::vector<DynamicsProcessing::EqBandConfig> bands;
+    if (tag == DynamicsProcessing::preEqBand) {
+        bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                aidlParam, DynamicsProcessing, dynamicsProcessing, preEqBand,
+                std::vector<DynamicsProcessing::EqBandConfig>));
+    } else if (tag == DynamicsProcessing::postEqBand) {
+        bands = VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                aidlParam, DynamicsProcessing, dynamicsProcessing, postEqBand,
+                std::vector<DynamicsProcessing::EqBandConfig>));
+    } else {
+        return BAD_VALUE;
+    }
+
+    for (const auto& bandIt : bands) {
+        if (bandIt.channel == channel && bandIt.band == band) {
+            int32_t enable = bandIt.enable;
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.cutoffFrequencyHz));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.gainDb));
+            return OK;
+        }
+    }
+    ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
+    return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getMbcBandConfig(EffectParamWriter& param) {
+    int32_t channel, band;
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&band));
+    Parameter aidlParam;
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+                                                  DynamicsProcessing::mbcBand);
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+    std::vector<DynamicsProcessing::MbcBandConfig> bands =
+            VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, DynamicsProcessing, dynamicsProcessing, mbcBand,
+                    std::vector<DynamicsProcessing::MbcBandConfig>));
+
+    for (const auto& bandIt : bands) {
+        if (bandIt.channel == channel && bandIt.band == band) {
+            int32_t enable = bandIt.enable;
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.cutoffFrequencyHz));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.attackTimeMs));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.releaseTimeMs));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.ratio));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.thresholdDb));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.kneeWidthDb));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.noiseGateThresholdDb));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.expanderRatio));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.preGainDb));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&bandIt.postGainDb));
+            return OK;
+        }
+    }
+    ALOGE("%s not able to find channel %d band %d", __func__, channel, band);
+    return BAD_VALUE;
+}
+
+status_t AidlConversionDp::getLimiterConfig(EffectParamWriter& param) {
+    int32_t channel;
+    RETURN_STATUS_IF_ERROR(param.readFromParameter(&channel));
+    Parameter aidlParam;
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(DynamicsProcessing, dynamicsProcessingTag,
+                                                  DynamicsProcessing::limiter);
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+
+    std::vector<DynamicsProcessing::LimiterConfig> configs =
+            VALUE_OR_RETURN_STATUS(aidl::android::GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, DynamicsProcessing, dynamicsProcessing, limiter,
+                    std::vector<DynamicsProcessing::LimiterConfig>));
+
+    for (const auto& config : configs) {
+        if (config.channel == channel) {
+            int32_t inUse = mEngine.limiterInUse;
+            int32_t enable = config.enable;
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&inUse));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&enable));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&config.linkGroup));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&config.attackTimeMs));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&config.releaseTimeMs));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&config.ratio));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&config.thresholdDb));
+            RETURN_STATUS_IF_ERROR(param.writeToValue(&config.postGainDb));
+            return OK;
+        }
+    }
+    ALOGE("%s not able to find channel %d", __func__, channel);
+    return BAD_VALUE;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
new file mode 100644
index 0000000..c5d5a54
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionDynamicsProcessing.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BpEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionDp : public EffectConversionHelperAidl {
+  public:
+    AidlConversionDp(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+                     int32_t sessionId, int32_t ioId,
+                     const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionDp() {}
+
+  private:
+    aidl::android::hardware::audio::effect::DynamicsProcessing::EngineArchitecture mEngine;
+
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+
+    ConversionResult<
+            aidl::android::hardware::audio::effect::DynamicsProcessing::ChannelConfig>
+    readChannelConfigFromParam(utils::EffectParamReader& param);
+    ConversionResult<aidl::android::hardware::audio::effect::DynamicsProcessing::EqBandConfig>
+    readEqBandConfigFromParam(utils::EffectParamReader& param);
+    ConversionResult<
+            aidl::android::hardware::audio::effect::DynamicsProcessing::MbcBandConfig>
+    readMbcBandConfigFromParam(utils::EffectParamReader& param);
+    ConversionResult<
+            aidl::android::hardware::audio::effect::DynamicsProcessing::LimiterConfig>
+    readLimiterConfigFromParam(utils::EffectParamReader& param);
+    ConversionResult<
+            aidl::android::hardware::audio::effect::DynamicsProcessing::EngineArchitecture>
+    readEngineArchitectureFromParam(utils::EffectParamReader& param);
+
+    status_t getChannelConfig(aidl::android::hardware::audio::effect::DynamicsProcessing::Tag tag,
+                              utils::EffectParamWriter& writer);
+    status_t getEqBandConfig(aidl::android::hardware::audio::effect::DynamicsProcessing::Tag tag,
+                             utils::EffectParamWriter& param);
+    status_t getMbcBandConfig(utils::EffectParamWriter& param);
+    status_t getLimiterConfig(utils::EffectParamWriter& param);
+
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
new file mode 100644
index 0000000..754da43
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionEnvReverb"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_environmentalreverb.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionEnvReverb.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::EnvironmentalReverb;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+/**
+ * Macro to get a parameter from effect_param_t wrapper and set it to AIDL effect.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamReader, a reader wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define SET_AIDL_PARAMETER(param, aidlType, valueType, tag)                                \
+    {                                                                                      \
+        Parameter aidlParam;                                                               \
+        valueType value;                                                                   \
+        if (status_t status = param.readFromValue(&value); status != OK) {                 \
+            ALOGE("%s  %s read from parameter failed, ret %d", __func__, #tag, status);    \
+            return status;                                                                 \
+        }                                                                                  \
+        aidlParam = MAKE_SPECIFIC_PARAMETER(                                               \
+                EnvironmentalReverb, environmentalReverb, tag,                             \
+                VALUE_OR_RETURN_STATUS(aidl::android::convertIntegral<aidlType>(value)));  \
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam))); \
+    }
+
+/**
+ * Macro to get a parameter from AIDL effect and write the value to effect_param_t with wrapper.
+ *
+ * Return if there is any error, otherwise continue execution.
+ *
+ * @param param EffectParamWriter, a writer wrapper of effect_param_t.
+ * @param aidlType Type of the AIDL parameter field, used to construct AIDL Parameter union.
+ * @param valueType  Type of the value get from effect_param_t.
+ * @param tag The AIDL parameter union field tag.
+ */
+#define GET_AIDL_PARAMETER(param, aidltype, valueType, tag)                                        \
+    {                                                                                              \
+        aidltype value;                                                                            \
+        Parameter aidlParam;                                                                       \
+        Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(EnvironmentalReverb, environmentalReverbTag, \
+                                                      EnvironmentalReverb::tag);                   \
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));    \
+        value = VALUE_OR_RETURN_STATUS(                                                            \
+                GET_PARAMETER_SPECIFIC_FIELD(aidlParam, EnvironmentalReverb, environmentalReverb,  \
+                                             EnvironmentalReverb::tag, std::decay_t<aidltype>));   \
+        if (status_t status = param.writeToValue((valueType*)&value); status != OK) {              \
+            param.setStatus(status);                                                               \
+            ALOGE("%s %s write to parameter failed %d, ret %d", __func__, #tag, value, status);    \
+            return status;                                                                         \
+        }                                                                                          \
+    }
+
+status_t AidlConversionEnvReverb::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    if (status_t status = param.readFromParameter(&type); status != OK) {
+        ALOGE("%s failed to read type from %s, ret %d", __func__, param.toString().c_str(), status);
+        return BAD_VALUE;
+    }
+
+    switch (type) {
+        case REVERB_PARAM_ROOM_LEVEL: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            break;
+        }
+        case REVERB_PARAM_ROOM_HF_LEVEL: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            break;
+        }
+        case REVERB_PARAM_DECAY_TIME: {
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            break;
+        }
+        case REVERB_PARAM_DECAY_HF_RATIO: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            break;
+        }
+        case REVERB_PARAM_REFLECTIONS_LEVEL: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+            break;
+        }
+        case REVERB_PARAM_REFLECTIONS_DELAY: {
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            break;
+        }
+        case REVERB_PARAM_REVERB_LEVEL: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            break;
+        }
+        case REVERB_PARAM_REVERB_DELAY: {
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            break;
+        }
+        case REVERB_PARAM_DIFFUSION: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            break;
+        }
+        case REVERB_PARAM_DENSITY: {
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+            break;
+        }
+        case REVERB_PARAM_BYPASS: {
+            SET_AIDL_PARAMETER(param, bool, int32_t, bypass);
+            break;
+        }
+        case REVERB_PARAM_PROPERTIES: {
+            if (sizeof(t_reverb_settings) > param.getValueSize()) {
+                ALOGE("%s vsize %zu less than t_reverb_settings size %zu", __func__,
+                      param.getValueSize(), sizeof(t_reverb_settings));
+                return BAD_VALUE;
+            }
+            // this sequency needs to be aligned with t_reverb_settings
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            SET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            SET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            Parameter aidlParam = MAKE_SPECIFIC_PARAMETER(EnvironmentalReverb,
+                                                          environmentalReverb, vendor, ext);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->setParameter(aidlParam)));
+            break;
+        }
+    }
+    return OK;
+}
+
+status_t AidlConversionEnvReverb::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (status_t status = param.readFromParameter(&type); status != OK) {
+        ALOGE("%s failed to read type from %s", __func__, param.toString().c_str());
+        param.setStatus(status);
+        return status;
+    }
+
+    switch (type) {
+        case REVERB_PARAM_ROOM_LEVEL: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            break;
+        }
+        case REVERB_PARAM_ROOM_HF_LEVEL: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            break;
+        }
+        case REVERB_PARAM_DECAY_TIME: {
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            break;
+        }
+        case REVERB_PARAM_DECAY_HF_RATIO: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            break;
+        }
+        case REVERB_PARAM_REFLECTIONS_LEVEL: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+            break;
+        }
+        case REVERB_PARAM_REFLECTIONS_DELAY: {
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            break;
+        }
+        case REVERB_PARAM_REVERB_LEVEL: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            break;
+        }
+        case REVERB_PARAM_REVERB_DELAY: {
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            break;
+        }
+        case REVERB_PARAM_DIFFUSION: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            break;
+        }
+        case REVERB_PARAM_DENSITY: {
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+            break;
+        }
+        case REVERB_PARAM_BYPASS: {
+            GET_AIDL_PARAMETER(param, bool, int32_t, bypass);
+            break;
+        }
+        case REVERB_PARAM_PROPERTIES: {
+            // this sequency needs to be aligned with t_reverb_settings
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomLevelMb);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, roomHfLevelMb);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, decayTimeMs);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, decayHfRatioPm);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, reflectionsLevelMb);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, reflectionsDelayMs);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, levelMb);
+            GET_AIDL_PARAMETER(param, int32_t, uint32_t, delayMs);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, diffusionPm);
+            GET_AIDL_PARAMETER(param, int32_t, int16_t, densityPm);
+            break;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(EnvironmentalReverb, environmentalReverb, param);
+        }
+    }
+    return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
new file mode 100644
index 0000000..8b92374
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEnvReverb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionEnvReverb : public EffectConversionHelperAidl {
+  public:
+    AidlConversionEnvReverb(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionEnvReverb() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
new file mode 100644
index 0000000..45b98a1
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.cpp
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionEQ"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_equalizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionEq.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Equalizer;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::base::unexpected;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionEq::setParameter(EffectParamReader& param) {
+    uint32_t type;
+    if (OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    Parameter aidlParam;
+    switch (type) {
+        case EQ_PARAM_CUR_PRESET: {
+            uint16_t value = 0;
+            if (OK != param.readFromValue(&value)) {
+                ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)value);
+            break;
+        }
+        case EQ_PARAM_BAND_LEVEL: {
+            int32_t band;
+            int16_t level;
+            if (OK != param.readFromParameter(&band) || OK != param.readFromValue(&level)) {
+                ALOGE("%s invalid bandLevel param %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            std::vector<Equalizer::BandLevel> bandLevels = {{.index = band, .levelMb = level}};
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
+            break;
+        }
+        case EQ_PARAM_PROPERTIES: {
+            int16_t num;
+            if (OK != param.readFromValue(&num)) {
+                ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            // set preset if it's valid
+            if (num >= 0) {
+                aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, preset, (int)num);
+                break;
+            }
+            // set bandLevel if no preset was set
+            if (OK != param.readFromValue(&num)) {
+                ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            std::vector<Equalizer::BandLevel> bandLevels;
+            for (int i = 0; i < num; i++) {
+                Equalizer::BandLevel level({.index = i});
+                if (OK != param.readFromValue((uint16_t*)&level.levelMb)) {
+                    ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+                    return BAD_VALUE;
+                }
+                bandLevels.push_back(level);
+            }
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, bandLevels, bandLevels);
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Equalizer, equalizer, vendor, ext);
+            break;
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+ConversionResult<Parameter> AidlConversionEq::getAidlParameter(Equalizer::Tag tag) {
+    Parameter aidlParam;
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Equalizer, equalizerTag, tag);
+    RETURN_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    return aidlParam;
+}
+
+ConversionResult<int32_t> AidlConversionEq::getParameterPreset() {
+    Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::preset));
+    return VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Equalizer, equalizer,
+                                                               Equalizer::preset, int32_t));
+}
+
+ConversionResult<std::string> AidlConversionEq::getParameterPresetName(
+        EffectParamWriter& param) {
+    int32_t presetIdx;
+    if (OK != param.readFromParameter(&presetIdx)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return unexpected(BAD_VALUE);
+    }
+    Parameter aidlParam = VALUE_OR_RETURN(getAidlParameter(Equalizer::presets));
+    const auto& presets = VALUE_OR_RETURN(GET_PARAMETER_SPECIFIC_FIELD(
+            aidlParam, Equalizer, equalizer, Equalizer::presets, std::vector<Equalizer::Preset>));
+    for (const auto& preset : presets) {
+        if (presetIdx == preset.index) {
+            return preset.name;
+        }
+    }
+    return unexpected(BAD_VALUE);
+}
+
+status_t AidlConversionEq::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (OK != param.readFromParameter(&type)) {
+        param.setStatus(BAD_VALUE);
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+
+    switch (type) {
+        case EQ_PARAM_NUM_BANDS: {
+            Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+            const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+                    std::vector<Equalizer::BandLevel>));
+            uint16_t bands = bandLevels.size();
+            return param.writeToValue(&bands);
+        }
+        case EQ_PARAM_LEVEL_RANGE: {
+            const auto& ranges = mDesc.capability.range.get<Range::equalizer>();
+            for (const auto& r : ranges) {
+                if (r.min.getTag() == Equalizer::bandLevels &&
+                    r.max.getTag() == Equalizer::bandLevels) {
+                    const auto& aidlMin = r.min.get<Equalizer::bandLevels>();
+                    const auto& aidlMax = r.max.get<Equalizer::bandLevels>();
+                    int16_t min =
+                            std::min_element(aidlMin.begin(), aidlMin.end(), [](auto& a, auto& b) {
+                                return a.levelMb < b.levelMb;
+                            })->levelMb;
+                    int16_t max =
+                            std::max_element(aidlMax.begin(), aidlMax.end(), [](auto& a, auto& b) {
+                                return a.levelMb < b.levelMb;
+                            })->levelMb;
+                    return (OK == param.writeToValue(&min) && OK == param.writeToValue(&max))
+                                   ? OK
+                                   : BAD_VALUE;
+                }
+            }
+            break;
+        }
+        case EQ_PARAM_BAND_LEVEL: {
+            int32_t bandIdx;
+            if (OK != param.readFromParameter(&bandIdx)) {
+                break;
+            }
+
+            Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+            const auto& bandLevels = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+                    std::vector<Equalizer::BandLevel>));
+            for (const auto& band : bandLevels) {
+                if (band.index == bandIdx) {
+                    return param.writeToValue((uint16_t *)&band.levelMb);
+                }
+            }
+            break;
+        }
+        case EQ_PARAM_CENTER_FREQ: {
+            int32_t index;
+            if (OK != param.readFromParameter(&index)) {
+                break;
+            }
+
+            Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::centerFreqMh));
+            const auto& freqs = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Equalizer, equalizer, Equalizer::centerFreqMh, std::vector<int>));
+            if ((size_t)index >= freqs.size()) {
+                ALOGE("%s index %d exceed size %zu", __func__, index, freqs.size());
+                break;
+            }
+            return param.writeToValue(&freqs[index]);
+        }
+        case EQ_PARAM_BAND_FREQ_RANGE: {
+            int32_t index;
+            if (OK != param.readFromParameter(&index)) {
+                break;
+            }
+
+            Parameter aidlParam =
+                    VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
+            const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
+                    std::vector<Equalizer::BandFrequency>));
+            for (const auto& band : bands) {
+                if (band.index == index) {
+                    return (OK == param.writeToValue(&band.minMh) &&
+                            OK == param.writeToValue(&band.maxMh))
+                                   ? OK
+                                   : BAD_VALUE;
+                }
+            }
+            break;
+        }
+        case EQ_PARAM_GET_BAND: {
+            int32_t freq;
+            if (OK != param.readFromParameter(&freq)) {
+                break;
+            }
+
+            Parameter aidlParam =
+                    VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandFrequencies));
+            const auto& bands = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Equalizer, equalizer, Equalizer::bandFrequencies,
+                    std::vector<Equalizer::BandFrequency>));
+            for (const auto& band : bands) {
+                if (freq >= band.minMh && freq <= band.maxMh) {
+                    return param.writeToValue((uint16_t*)&band.index);
+                }
+            }
+            break;
+        }
+        case EQ_PARAM_CUR_PRESET: {
+            int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
+            return param.writeToValue((uint16_t*)&preset);
+        }
+        case EQ_PARAM_GET_NUM_OF_PRESETS: {
+            Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::presets));
+            const auto& presets = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Equalizer, equalizer, Equalizer::presets,
+                    std::vector<Equalizer::Preset>));
+            uint16_t num = presets.size();
+            return param.writeToValue(&num);
+        }
+        case EQ_PARAM_GET_PRESET_NAME: {
+            std::string name = VALUE_OR_RETURN_STATUS(getParameterPresetName(param));
+            return param.writeToValue(name.c_str(), name.length());
+        }
+        case EQ_PARAM_PROPERTIES: {
+            int32_t preset = VALUE_OR_RETURN_STATUS(getParameterPreset());
+            if (OK != param.writeToValue((uint16_t*)&preset)) {
+                break;
+            }
+            Parameter aidlParam = VALUE_OR_RETURN_STATUS(getAidlParameter(Equalizer::bandLevels));
+            std::vector<Equalizer::BandLevel> bandLevels =
+                    VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                            aidlParam, Equalizer, equalizer, Equalizer::bandLevels,
+                            std::vector<Equalizer::BandLevel>));
+            uint16_t bands = bandLevels.size();
+            if (OK != param.writeToValue(&bands)) {
+                break;
+            }
+            std::sort(bandLevels.begin(), bandLevels.end(),
+                      [](const auto& a, const auto& b) { return a.index < b.index; });
+            for (const auto& level : bandLevels) {
+                if (status_t status = param.writeToValue((uint16_t*)&level.levelMb); status != OK) {
+                    return status;
+                }
+            }
+            return OK;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(Equalizer, equalizer, param);
+        }
+    }
+
+    param.setStatus(BAD_VALUE);
+    ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+    return BAD_VALUE;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
new file mode 100644
index 0000000..f94556c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionEq.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionEq : public EffectConversionHelperAidl {
+  public:
+    AidlConversionEq(std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+                      int32_t sessionId, int32_t ioId,
+                      const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionEq() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+    ConversionResult<::aidl::android::hardware::audio::effect::Parameter> getAidlParameter(
+            ::aidl::android::hardware::audio::effect::Equalizer::Tag tag);
+    ConversionResult<int32_t> getParameterPreset();
+    ConversionResult<std::string> getParameterPresetName(utils::EffectParamWriter& param);
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
new file mode 100644
index 0000000..73430ba
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionHapticGenerator"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionHapticGenerator.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::HapticGenerator;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionHapticGenerator::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case HG_PARAM_HAPTIC_INTENSITY: {
+            int32_t id = 0, scale;
+            if (OK != param.readFromValue(&id) || OK != param.readFromValue(&scale)) {
+                ALOGE("%s invalid intensity %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            HapticGenerator::HapticScale hpScale(
+                    {.id = id, .scale = (HapticGenerator::VibratorScale)(scale)});
+            aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, hapticScales,
+                                                {hpScale});
+            break;
+        }
+        case HG_PARAM_VIBRATOR_INFO: {
+            float resonantFrequencyHz, qFactor, maxAmplitude;
+            if (OK != param.readFromValue(&resonantFrequencyHz) ||
+                OK != param.readFromValue(&qFactor) || OK != param.readFromValue(&maxAmplitude)) {
+                ALOGE("%s invalid vibrator info %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            HapticGenerator::VibratorInformation info({.resonantFrequencyHz = resonantFrequencyHz,
+                                                       .qFactor = qFactor,
+                                                       .maxAmplitude = maxAmplitude});
+            aidlParam =
+                    MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vibratorInfo, info);
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(HapticGenerator, hapticGenerator, vendor, ext);
+            break;
+        }
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+// No parameter to get for HapticGenerator
+status_t AidlConversionHapticGenerator::getParameter(EffectParamWriter& param) {
+    VENDOR_EXTENSION_GET_AND_RETURN(HapticGenerator, hapticGenerator, param);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
new file mode 100644
index 0000000..03114a5
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionHapticGenerator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionHapticGenerator : public EffectConversionHelperAidl {
+  public:
+    AidlConversionHapticGenerator(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionHapticGenerator() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
new file mode 100644
index 0000000..31eec65
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionLoudnessEnhancer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionLoudnessEnhancer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::LoudnessEnhancer;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionLoudnessEnhancer::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    int32_t gain = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type) || OK != param.readFromValue(&gain)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+            aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, gainMb, gain);
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(LoudnessEnhancer, loudnessEnhancer, vendor, ext);
+            break;
+        }
+    }
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionLoudnessEnhancer::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    switch (type) {
+        case LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB: {
+            Parameter aidlParam;
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(LoudnessEnhancer, loudnessEnhancerTag,
+                                                        LoudnessEnhancer::gainMb);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            int32_t gain = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, LoudnessEnhancer, loudnessEnhancer, LoudnessEnhancer::gainMb,
+                    std::decay_t<decltype(gain)>));
+            return param.writeToValue(&gain);
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(LoudnessEnhancer, loudnessEnhancer, param);
+        }
+    }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
new file mode 100644
index 0000000..c0402f9
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionLoudnessEnhancer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionLoudnessEnhancer : public EffectConversionHelperAidl {
+  public:
+    AidlConversionLoudnessEnhancer(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionLoudnessEnhancer() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
new file mode 100644
index 0000000..7c34ed7
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionNoiseSuppression"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_ns.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionNoiseSuppression.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::NoiseSuppression;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionNoiseSuppression::setParameter(EffectParamReader& param) {
+    uint32_t type = 0, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case NS_PARAM_LEVEL: {
+            aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, level,
+                                                static_cast<NoiseSuppression::Level>(value));
+            break;
+        }
+        case NS_PARAM_TYPE: {
+            aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, type,
+                                                static_cast<NoiseSuppression::Type>(value));
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(NoiseSuppression, noiseSuppression, vendor, ext);
+            break;
+        }
+    }
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionNoiseSuppression::getParameter(EffectParamWriter& param) {
+    uint32_t paramType = 0, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&paramType)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (paramType) {
+        case NS_PARAM_LEVEL: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(NoiseSuppression, noiseSuppressionTag,
+                                                        NoiseSuppression::level);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            NoiseSuppression::Level level = VALUE_OR_RETURN_STATUS(
+                    GET_PARAMETER_SPECIFIC_FIELD(aidlParam, NoiseSuppression, noiseSuppression,
+                                                 NoiseSuppression::level, NoiseSuppression::Level));
+            value = static_cast<uint32_t>(level);
+            break;
+        }
+        case NS_PARAM_TYPE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(NoiseSuppression, noiseSuppressionTag,
+                                                        NoiseSuppression::type);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            NoiseSuppression::Type nsType = VALUE_OR_RETURN_STATUS(
+                    GET_PARAMETER_SPECIFIC_FIELD(aidlParam, NoiseSuppression, noiseSuppression,
+                                                 NoiseSuppression::type, NoiseSuppression::Type));
+            value = static_cast<uint32_t>(nsType);
+            break;
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(NoiseSuppression, noiseSuppression, param);
+        }
+    }
+    return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
new file mode 100644
index 0000000..f51e13a
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionNoiseSuppression.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionNoiseSuppression : public EffectConversionHelperAidl {
+  public:
+    AidlConversionNoiseSuppression(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionNoiseSuppression() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp
new file mode 100644
index 0000000..e936aef
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionPresetReverb"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_presetreverb.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionPresetReverb.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::convertIntegral;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::PresetReverb;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionPresetReverb::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    if (type == REVERB_PARAM_PRESET) {
+        uint16_t value = 0;
+        if (OK != param.readFromValue(&value)) {
+            ALOGE("%s invalid preset value %s", __func__, param.toString().c_str());
+            return BAD_VALUE;
+        }
+        aidlParam = MAKE_SPECIFIC_PARAMETER(PresetReverb, presetReverb, preset,
+                                            static_cast<PresetReverb::Presets>(value));
+    } else {
+        // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+        VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+        aidlParam = MAKE_SPECIFIC_PARAMETER(PresetReverb, presetReverb, vendor, ext);
+    }
+
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionPresetReverb::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    uint16_t value = 0;
+    ALOGE("%s enter %s", __func__, param.toString().c_str());
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint16_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    if (type == REVERB_PARAM_PRESET) {
+        Parameter aidlParam;
+        Parameter::Id id =
+                MAKE_SPECIFIC_PARAMETER_ID(PresetReverb, presetReverbTag, PresetReverb::preset);
+        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+        auto aidlPreset = VALUE_OR_RETURN_STATUS(
+                GET_PARAMETER_SPECIFIC_FIELD(aidlParam, PresetReverb, presetReverb,
+                                             PresetReverb::preset, PresetReverb::Presets));
+        value = static_cast<uint16_t>(aidlPreset);
+    } else {
+        // handle vendor extension
+        VENDOR_EXTENSION_GET_AND_RETURN(PresetReverb, presetReverb, param);
+    }
+    return param.writeToValue(&value);
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
new file mode 100644
index 0000000..397d6e6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionPresetReverb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionPresetReverb : public EffectConversionHelperAidl {
+  public:
+    AidlConversionPresetReverb(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionPresetReverb() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
new file mode 100644
index 0000000..eadd6c3
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionSpatializer"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_spatializer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionSpatializer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionSpatializer::setParameter(EffectParamReader& param) {
+    Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionSpatializer::getParameter(EffectParamWriter& param) {
+    DefaultExtension defaultExt;
+    // read parameters into DefaultExtension vector<uint8_t>
+    if (OK != param.readFromParameter(defaultExt.bytes.data(), param.getParameterSize())) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+
+    VendorExtension idTag;
+    idTag.extension.setParcelable(defaultExt);
+    Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, idTag);
+    Parameter aidlParam;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    // copy the AIDL extension data back to effect_param_t
+    return VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam,
+                                                                                  param));
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
new file mode 100644
index 0000000..c44567c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionSpatializer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionSpatializer : public EffectConversionHelperAidl {
+  public:
+    AidlConversionSpatializer(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionSpatializer() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
new file mode 100644
index 0000000..488d5cd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#include <type_traits>
+#define LOG_TAG "AidlConversionVendorExtension"
+//#define LOG_NDEBUG 0
+
+#include <aidl/android/hardware/audio/effect/DefaultExtension.h>
+#include <aidl/android/hardware/audio/effect/VendorExtension.h>
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVendorExtension.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::DefaultExtension;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+/**
+ * For all effect types we currently don't support, add a default extension implementation to use
+ * std::vector<uint8_t> to pass through all data in the format of effect_param_t (the data we got
+ * from libaudioclient for now).
+ * This logic will be removed after we adopt to same AIDL parameter union AIDL in libaudioclient,
+ * after that framework doesn't need to do any AIDL conversion, and the vendor extension can be
+ * pass down in Parameter as is.
+ */
+status_t AidlConversionVendorExtension::setParameter(EffectParamReader& param) {
+    Parameter aidlParam = VALUE_OR_RETURN_STATUS(
+            ::aidl::android::legacy2aidl_EffectParameterReader_ParameterExtension(param));
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVendorExtension::getParameter(EffectParamWriter& param) {
+    VendorExtension extId = VALUE_OR_RETURN_STATUS(
+            aidl::android::legacy2aidl_EffectParameterReader_Param_VendorExtension(param));
+    Parameter::Id id = UNION_MAKE(Parameter::Id, vendorEffectTag, extId);
+    Parameter aidlParam;
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    // copy the AIDL extension data back to effect_param_t
+    return VALUE_OR_RETURN_STATUS(
+            ::aidl::android::aidl2legacy_ParameterExtension_EffectParameterWriter(aidlParam,
+                                                                                  param));
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
new file mode 100644
index 0000000..fd22e5c
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVendorExtension.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVendorExtension : public EffectConversionHelperAidl {
+  public:
+    AidlConversionVendorExtension(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionVendorExtension() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
new file mode 100644
index 0000000..c95c3a9
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionVirtualizer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/aidl_effects_utils.h>
+#include <system/audio_effects/effect_virtualizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVirtualizer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::Range;
+using ::aidl::android::hardware::audio::effect::Virtualizer;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionVirtualizer::setParameter(EffectParamReader& param) {
+    uint32_t type = 0;
+    if (OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case VIRTUALIZER_PARAM_STRENGTH: {
+            int16_t strength = 0;
+            if (OK != param.readFromValue(&strength)) {
+                ALOGE("%s invalid param %s for type %d", __func__, param.toString().c_str(), type);
+                return BAD_VALUE;
+            }
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, strengthPm, strength);
+            break;
+        }
+        case VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE: {
+            audio_devices_t deviceType;
+            if (OK != param.readFromValue(&deviceType)) {
+                ALOGE("%s invalid param %s for type %d", __func__, param.toString().c_str(), type);
+                return BAD_VALUE;
+            }
+            AudioDeviceDescription deviceDesc = VALUE_OR_RETURN_STATUS(
+                    ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+                            deviceType));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, device, deviceDesc);
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Virtualizer, virtualizer, vendor, ext);
+            break;
+        }
+    }
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVirtualizer::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0;
+    if (OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case VIRTUALIZER_PARAM_STRENGTH_SUPPORTED: {
+            // an invalid range indicates not setting support for this parameter
+            uint32_t support =
+                    ::aidl::android::hardware::audio::effect::isRangeValid<Range::Tag::virtualizer>(
+                            Virtualizer::strengthPm, mDesc.capability);
+            return param.writeToValue(&support);
+        }
+        case VIRTUALIZER_PARAM_STRENGTH: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Virtualizer, virtualizerTag,
+                                                          Virtualizer::strengthPm);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            int16_t strength = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Virtualizer, virtualizer, Virtualizer::strengthPm, int32_t));
+            return param.writeToValue(&strength);
+        }
+        case VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES: {
+            audio_channel_mask_t mask;
+            audio_devices_t device;
+            if (OK != param.readFromParameter(&mask) || OK != param.readFromParameter(&device)) {
+                ALOGW("%s illegal param %s", __func__, param.toString().c_str());
+                return BAD_VALUE;
+            }
+            Virtualizer::SpeakerAnglesPayload payload = {
+                    .layout = VALUE_OR_RETURN_STATUS(
+                            ::aidl::android::legacy2aidl_audio_channel_mask_t_AudioChannelLayout(
+                                    mask, false)),
+                    .device = VALUE_OR_RETURN_STATUS(
+                            ::aidl::android::legacy2aidl_audio_devices_t_AudioDeviceDescription(
+                                    device))};
+            Virtualizer::Id vId = UNION_MAKE(Virtualizer::Id, speakerAnglesPayload, payload);
+            Parameter::Id id = UNION_MAKE(Parameter::Id, virtualizerTag, vId);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            const auto& angles = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Virtualizer, virtualizer, Virtualizer::speakerAngles,
+                    std::vector<Virtualizer::ChannelAngle>));
+            for (const auto& angle : angles) {
+                const audio_channel_mask_t chMask = ::aidl::android::
+                        aidl2legacy_AudioChannelLayout_layout_audio_channel_mask_t_bits(
+                                angle.channel, false);
+                ALOGW("%s aidl %d ch %d", __func__, angle.channel, chMask);
+                if (OK != param.writeToValue(&chMask) ||
+                    OK != param.writeToValue(&angle.azimuthDegree) ||
+                    OK != param.writeToValue(&angle.elevationDegree)) {
+                    ALOGW("%s can't write angles to param %s", __func__, param.toString().c_str());
+                    return BAD_VALUE;
+                }
+            }
+            return OK;
+        }
+        case VIRTUALIZER_PARAM_VIRTUALIZATION_MODE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Virtualizer, virtualizerTag,
+                                                          Virtualizer::device);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            AudioDeviceDescription device = VALUE_OR_RETURN_STATUS(
+                    GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Virtualizer, virtualizer,
+                                                 Virtualizer::device, AudioDeviceDescription));
+            const audio_devices_t deviceType = VALUE_OR_RETURN_STATUS(
+                    ::aidl::android::aidl2legacy_AudioDeviceDescription_audio_devices_t(device));
+            return param.writeToValue(&deviceType);
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(Virtualizer, virtualizer, param);
+        }
+    }
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
new file mode 100644
index 0000000..91c0fcd
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVirtualizer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVirtualizer : public EffectConversionHelperAidl {
+  public:
+    AidlConversionVirtualizer(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionVirtualizer() {}
+
+  private:
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
new file mode 100644
index 0000000..2d5af59
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <optional>
+#define LOG_TAG "AidlConversionVisualizer"
+//#define LOG_NDEBUG 0
+
+#include <error/expected_utils.h>
+#include <media/AidlConversionNdk.h>
+#include <media/AidlConversionEffect.h>
+#include <system/audio_effects/effect_visualizer.h>
+
+#include <utils/Log.h>
+
+#include "AidlConversionVisualizer.h"
+
+namespace android {
+namespace effect {
+
+using ::aidl::android::getParameterSpecificField;
+using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::effect::Parameter;
+using ::aidl::android::hardware::audio::effect::VendorExtension;
+using ::aidl::android::hardware::audio::effect::Visualizer;
+using ::android::status_t;
+using utils::EffectParamReader;
+using utils::EffectParamWriter;
+
+status_t AidlConversionVisualizer::setParameter(EffectParamReader& param) {
+    uint32_t type = 0, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(uint32_t)) ||
+        OK != param.readFromParameter(&type) || OK != param.readFromValue(&value)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case VISUALIZER_PARAM_CAPTURE_SIZE: {
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, captureSamples, value);
+            break;
+        }
+        case VISUALIZER_PARAM_SCALING_MODE: {
+            Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_Parameter_Visualizer_uint32_ScalingMode(value));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, scalingMode, mode);
+            break;
+        }
+        case VISUALIZER_PARAM_LATENCY: {
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, latencyMs, value);
+            break;
+        }
+        case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+            Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_Parameter_Visualizer_uint32_MeasurementMode(value));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, measurementMode, mode);
+            break;
+        }
+        default: {
+            // for vendor extension, copy data area to the DefaultExtension, parameter ignored
+            VendorExtension ext = VALUE_OR_RETURN_STATUS(
+                    aidl::android::legacy2aidl_EffectParameterReader_Data_VendorExtension(param));
+            aidlParam = MAKE_SPECIFIC_PARAMETER(Visualizer, visualizer, vendor, ext);
+            break;
+        }
+    }
+    return statusTFromBinderStatus(mEffect->setParameter(aidlParam));
+}
+
+status_t AidlConversionVisualizer::getParameter(EffectParamWriter& param) {
+    uint32_t type = 0, value = 0;
+    if (!param.validateParamValueSize(sizeof(uint32_t), sizeof(int32_t)) ||
+        OK != param.readFromParameter(&type)) {
+        ALOGE("%s invalid param %s", __func__, param.toString().c_str());
+        param.setStatus(BAD_VALUE);
+        return BAD_VALUE;
+    }
+    Parameter aidlParam;
+    switch (type) {
+        case VISUALIZER_PARAM_CAPTURE_SIZE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+                                                          Visualizer::captureSamples);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Visualizer, visualizer, Visualizer::captureSamples, int32_t));
+            mCaptureSize = value;
+            return param.writeToValue(&value);
+        }
+        case VISUALIZER_PARAM_SCALING_MODE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+                                                          Visualizer::scalingMode);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            Visualizer::ScalingMode mode = VALUE_OR_RETURN_STATUS(
+                    GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+                                                 Visualizer::scalingMode, Visualizer::ScalingMode));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_Visualizer_ScalingMode_uint32(mode));
+            return param.writeToValue(&value);
+        }
+        case VISUALIZER_PARAM_LATENCY: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+                                                          Visualizer::latencyMs);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            value = (int32_t)VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Visualizer, visualizer, Visualizer::latencyMs, int32_t));
+            return param.writeToValue(&value);
+        }
+        case VISUALIZER_PARAM_MEASUREMENT_MODE: {
+            Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+                                                          Visualizer::measurementMode);
+            RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+            Visualizer::MeasurementMode mode = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+                    aidlParam, Visualizer, visualizer, Visualizer::measurementMode,
+                    Visualizer::MeasurementMode));
+            value = VALUE_OR_RETURN_STATUS(
+                    aidl::android::aidl2legacy_Parameter_Visualizer_MeasurementMode_uint32(mode));
+            return param.writeToValue(&value);
+        }
+        default: {
+            VENDOR_EXTENSION_GET_AND_RETURN(Visualizer, visualizer, param);
+        }
+    }
+}
+
+status_t AidlConversionVisualizer::visualizerCapture(uint32_t* replySize, void* pReplyData) {
+    if (!replySize || !pReplyData || *replySize != mCaptureSize) {
+        ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    Parameter aidlParam;
+    Parameter::Id id = MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag,
+                                                    Visualizer::captureSampleBuffer);
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    const auto& samples = VALUE_OR_RETURN_STATUS(
+            GET_PARAMETER_SPECIFIC_FIELD(aidlParam, Visualizer, visualizer,
+                                         Visualizer::captureSampleBuffer, std::vector<uint8_t>));
+    size_t len = std::min((size_t)*replySize, samples.size());
+    std::memcpy(pReplyData, samples.data(), *replySize = len);
+    return OK;
+}
+
+status_t AidlConversionVisualizer::visualizerMeasure(uint32_t* replySize, void* pReplyData) {
+    if (!replySize || !pReplyData || *replySize != 2 * sizeof(int32_t)) {
+        ALOGE("%s illegal param replySize %p pReplyData %p", __func__, replySize, pReplyData);
+        return BAD_VALUE;
+    }
+
+    Parameter aidlParam;
+    Parameter::Id id =
+            MAKE_SPECIFIC_PARAMETER_ID(Visualizer, visualizerTag, Visualizer::measurement);
+    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mEffect->getParameter(id, &aidlParam)));
+    const auto& measure = VALUE_OR_RETURN_STATUS(GET_PARAMETER_SPECIFIC_FIELD(
+            aidlParam, Visualizer, visualizer, Visualizer::measurement, Visualizer::Measurement));
+    int32_t* reply = (int32_t *) pReplyData;
+    *reply++ = measure.rms;
+    *reply = measure.peak;
+    return OK;
+}
+
+} // namespace effect
+} // namespace android
diff --git a/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
new file mode 100644
index 0000000..e380bc6
--- /dev/null
+++ b/media/libaudiohal/impl/effectsAidlConversion/AidlConversionVisualizer.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include "EffectConversionHelperAidl.h"
+
+namespace android {
+namespace effect {
+
+class AidlConversionVisualizer : public EffectConversionHelperAidl {
+  public:
+    AidlConversionVisualizer(
+            std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect> effect,
+            int32_t sessionId, int32_t ioId,
+            const ::aidl::android::hardware::audio::effect::Descriptor& desc)
+        : EffectConversionHelperAidl(effect, sessionId, ioId, desc) {}
+    ~AidlConversionVisualizer() {}
+
+  private:
+    uint32_t mCaptureSize = 0;
+    status_t setParameter(utils::EffectParamReader& param) override;
+    status_t getParameter(utils::EffectParamWriter& param) override;
+    status_t visualizerCapture(uint32_t* replySize, void* pReplyData) override;
+    status_t visualizerMeasure(uint32_t* replySize, void* pReplyData) override;
+};
+
+}  // namespace effect
+}  // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h b/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h
new file mode 100644
index 0000000..6e09463
--- /dev/null
+++ b/media/libaudiohal/include/media/audiohal/AudioHalVersionInfo.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include <utility>
+#include <android/media/AudioHalVersion.h>
+
+namespace android::detail {
+
+class AudioHalVersionInfo : public android::media::AudioHalVersion {
+  public:
+    AudioHalVersionInfo(Type halType, int halMajor, int halMinor = 0) {
+        type = halType;
+        major = halMajor;
+        minor = halMinor;
+    }
+
+    Type getType() const { return type; }
+
+    int getMajorVersion() const { return major; }
+
+    int getMinorVersion() const { return minor; }
+
+    /** Keep HIDL version format as is for backward compatibility, only add prefix for AIDL. */
+    std::string toVersionString() const {
+        std::string versionStr =
+                android::internal::ToString(major) + "." + android::internal::ToString(minor);
+        if (type == Type::AIDL) {
+            return "aidl";
+        } else {
+            return versionStr;
+        }
+    }
+};
+
+} // namespace android
diff --git a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
index d27ad4c..c685345 100644
--- a/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DeviceHalInterface.h
@@ -21,7 +21,6 @@
 #include <android/media/audio/common/AudioMMapPolicyType.h>
 #include <error/Result.h>
 #include <media/audiohal/EffectHalInterface.h>
-#include <media/MicrophoneInfo.h>
 #include <system/audio.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -32,7 +31,7 @@
 class StreamInHalInterface;
 class StreamOutHalInterface;
 
-class DeviceHalInterface : public RefBase
+class DeviceHalInterface : public virtual RefBase
 {
   public:
     // Sets the value of 'devices' to a bitmask of 1 or more values of audio_devices_t.
@@ -107,7 +106,7 @@
     virtual status_t releaseAudioPatch(audio_patch_handle_t patch) = 0;
 
     // Fills the list of supported attributes for a given audio port.
-    virtual status_t getAudioPort(struct audio_port *port) = 0;
+    virtual status_t getAudioPort(struct audio_port* port) = 0;
 
     // Fills the list of supported attributes for a given audio port.
     virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
@@ -116,7 +115,8 @@
     virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
 
     // List microphones
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+    virtual status_t getMicrophones(
+            std::vector<audio_microphone_characteristic_t>* microphones) = 0;
 
     virtual status_t addDeviceEffect(
             audio_port_handle_t device, sp<EffectHalInterface> effect) = 0;
@@ -125,12 +125,16 @@
 
     virtual status_t getMmapPolicyInfos(
             media::audio::common::AudioMMapPolicyType policyType,
-            std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos)  = 0;
+            std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
     virtual int32_t getAAudioMixerBurstCount() = 0;
     virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+    virtual int32_t supportsBluetoothVariableLatency(bool* supports) = 0;
 
     // Update the connection status of an external device.
-    virtual status_t setConnectedState(const struct audio_port_v7 *port, bool connected) = 0;
+    virtual status_t setConnectedState(const struct audio_port_v7* port, bool connected) {
+        ALOGE("%s override me port %p connected %d", __func__, port, connected);
+        return OK;
+    }
 
     virtual error::Result<audio_hw_sync_t> getHwAvSync() = 0;
 
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index 17010e6..be3a723 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
+#pragma once
 
 #include <media/audiohal/DeviceHalInterface.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <vector>
 
+#include "AudioHalVersionInfo.h"
+
 namespace android {
 
 class DevicesFactoryHalCallback : public RefBase
@@ -43,7 +44,7 @@
     // The callback can be only set once.
     virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
 
-    virtual float getHalVersion() const = 0;
+    virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
 
     static sp<DevicesFactoryHalInterface> create();
 
@@ -55,5 +56,3 @@
 };
 
 } // namespace android
-
-#endif // ANDROID_HARDWARE_DEVICES_FACTORY_HAL_INTERFACE_H
diff --git a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
index 3e505bd..d740fe9 100644
--- a/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/EffectsFactoryHalInterface.h
@@ -14,14 +14,16 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
-#define ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
+#pragma once
 
 #include <media/audiohal/EffectHalInterface.h>
 #include <system/audio_effect.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
+#include "AudioHalVersionInfo.h"
+#include "FactoryHal.h"
+
 namespace android {
 
 class EffectsFactoryHalInterface : public RefBase
@@ -49,16 +51,16 @@
 
     virtual status_t dumpEffects(int fd) = 0;
 
-    virtual float getHalVersion() = 0;
-
     static sp<EffectsFactoryHalInterface> create();
 
     virtual status_t allocateBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
     virtual status_t mirrorBuffer(void* external, size_t size,
                                   sp<EffectBufferHalInterface>* buffer) = 0;
 
+    virtual android::detail::AudioHalVersionInfo getHalVersion() const = 0;
+
     // Helper function to compare effect uuid to EFFECT_UUID_NULL.
-    static bool isNullUuid(const effect_uuid_t *pEffectUuid);
+    static bool isNullUuid(const effect_uuid_t* pEffectUuid);
 
   protected:
     // Subclasses can not be constructed directly by clients.
@@ -68,5 +70,3 @@
 };
 
 } // namespace android
-
-#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_INTERFACE_H
diff --git a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h b/media/libaudiohal/include/media/audiohal/FactoryHal.h
similarity index 62%
rename from media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
rename to media/libaudiohal/include/media/audiohal/FactoryHal.h
index 866dd3e..4776d98 100644
--- a/media/libaudiohal/include/media/audiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/include/media/audiohal/FactoryHal.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,24 +14,19 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
-#define ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
+#pragma once
 
 #include <string>
 #include <utility>
-
 #include <utils/StrongPointer.h>
 
+#include "AudioHalVersionInfo.h"
+
 namespace android {
 
-// The pair of the interface's package name and the interface name,
-// e.g. <"android.hardware.audio", "IDevicesFactory">.
-// Splitting is used for easier construction of versioned names (FQNs).
-using InterfaceName = std::pair<std::string, std::string>;
-
 namespace detail {
 
-void* createPreferredImpl(const InterfaceName& iface, const InterfaceName& siblingIface);
+void* createPreferredImpl(bool isCore);
 
 }  // namespace detail
 
@@ -45,17 +40,12 @@
  * shared libraries the loader function considers which interface among two has the most
  * recent version. Thus, a pair of interface names must be passed in.
  *
- * @param iface the interface that needs to be created.
- * @param siblingIface the interface which occupies the same shared library.
+ * @param isCore Indicating if this is audio Core HAL service interface.
  * @return the preferred available implementation or nullptr if none are available.
  */
+
 template <class Interface>
-static sp<Interface> createPreferredImpl(
-        const InterfaceName& iface, const InterfaceName& siblingIface) {
-    return sp<Interface>{
-        static_cast<Interface*>(detail::createPreferredImpl(iface, siblingIface))};
+static sp<Interface> createPreferredImpl(bool isCore) {
+    return sp<Interface>{static_cast<Interface*>(detail::createPreferredImpl(isCore))};
 }
-
 } // namespace android
-
-#endif // ANDROID_HARDWARE_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index 1d52b7d..a780a17 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -19,8 +19,8 @@
 
 #include <vector>
 
+#include <android/media/MicrophoneInfoFw.h>
 #include <media/audiohal/EffectHalInterface.h>
-#include <media/MicrophoneInfo.h>
 #include <system/audio.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -110,8 +110,8 @@
     virtual void onError() {}
 
   protected:
-    StreamOutHalInterfaceCallback() {}
-    virtual ~StreamOutHalInterfaceCallback() {}
+    StreamOutHalInterfaceCallback() = default;
+    virtual ~StreamOutHalInterfaceCallback() = default;
 };
 
 class StreamOutHalInterfaceEventCallback : public virtual RefBase {
@@ -119,8 +119,8 @@
     virtual void onCodecFormatChanged(const std::basic_string<uint8_t>& metadataBs) = 0;
 
 protected:
-    StreamOutHalInterfaceEventCallback() {}
-    virtual ~StreamOutHalInterfaceEventCallback() {}
+    StreamOutHalInterfaceEventCallback() = default;
+    virtual ~StreamOutHalInterfaceEventCallback() = default;
 };
 
 class StreamOutHalInterfaceLatencyModeCallback : public virtual RefBase {
@@ -131,8 +131,8 @@
     virtual void onRecommendedLatencyModeChanged(std::vector<audio_latency_mode_t> modes) = 0;
 
 protected:
-    StreamOutHalInterfaceLatencyModeCallback() {}
-    virtual ~StreamOutHalInterfaceLatencyModeCallback() {}
+    StreamOutHalInterfaceLatencyModeCallback() = default;
+    virtual ~StreamOutHalInterfaceLatencyModeCallback() = default;
 };
 
 class StreamOutHalInterface : public virtual StreamHalInterface {
@@ -273,7 +273,7 @@
     virtual status_t getCapturePosition(int64_t *frames, int64_t *time) = 0;
 
     // Get active microphones
-    virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
+    virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
 
     // Set direction for capture processing
     virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t) = 0;
diff --git a/media/libaudiohal/tests/Android.bp b/media/libaudiohal/tests/Android.bp
new file mode 100644
index 0000000..2f78dd0
--- /dev/null
+++ b/media/libaudiohal/tests/Android.bp
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Headers module is in frameworks/av/Android.bp because modules are not allowed
+// to refer to headers in parent directories and the headers live in
+// frameworks/av/include.
+
+package {
+    default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_test {
+    name: "EffectsFactoryHalInterfaceTest",
+    test_suites: ["device-tests"],
+
+    srcs: [
+        "EffectsFactoryHalInterface_test.cpp",
+    ],
+
+    defaults: [
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+        "-Wthread-safety",
+        "-DBACKEND_NDK",
+    ],
+
+    shared_libs: [
+        "audioclient-types-aidl-cpp",
+        "libaudio_aidl_conversion_common_ndk",
+        "libaudiohal",
+        "liblog",
+        "libutils",
+        "libvibrator",
+    ],
+
+    header_libs: [
+        "libaudiohal_headers",
+    ],
+}
diff --git a/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
new file mode 100644
index 0000000..c076ccc
--- /dev/null
+++ b/media/libaudiohal/tests/EffectsFactoryHalInterface_test.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <utility>
+#define LOG_TAG "EffectsFactoryHalInterfaceTest"
+
+#include <aidl/android/media/audio/common/AudioUuid.h>
+#include <media/AidlConversionCppNdk.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <system/audio_effects/audio_effects_utils.h>
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_agc.h>
+#include <system/audio_effects/effect_agc2.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_downmix.h>
+#include <system/audio_effects/effect_dynamicsprocessing.h>
+#include <system/audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effect.h>
+
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibrationUtils.h>
+
+namespace android {
+
+using effect::utils::EffectParamReader;
+using effect::utils::EffectParamWriter;
+using ::aidl::android::media::audio::common::AudioUuid;
+
+// EffectsFactoryHalInterface
+TEST(libAudioHalTest, createEffectsFactoryHalInterface) {
+    ASSERT_NE(nullptr, EffectsFactoryHalInterface::create());
+}
+
+TEST(libAudioHalTest, queryNumberEffects) {
+    auto factory = EffectsFactoryHalInterface::create();
+    ASSERT_NE(nullptr, factory);
+
+    uint32_t numEffects = 0;
+    EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
+    EXPECT_NE(0ul, numEffects);
+}
+
+TEST(libAudioHalTest, getDescriptorByNumber) {
+    auto factory = EffectsFactoryHalInterface::create();
+    ASSERT_NE(nullptr, factory);
+
+    uint32_t numEffects = 0;
+    EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
+    EXPECT_NE(0ul, numEffects);
+
+    effect_descriptor_t desc;
+    for (uint32_t i = 0; i < numEffects; i++) {
+        EXPECT_EQ(OK, factory->getDescriptor(i, &desc));
+    }
+}
+
+TEST(libAudioHalTest, createEffect) {
+    auto factory = EffectsFactoryHalInterface::create();
+    ASSERT_NE(nullptr, factory);
+
+    uint32_t numEffects = 0;
+    EXPECT_EQ(OK, factory->queryNumberEffects(&numEffects));
+    EXPECT_NE(0ul, numEffects);
+
+    effect_descriptor_t desc;
+    for (uint32_t i = 0; i < numEffects; i++) {
+        sp<EffectHalInterface> interface;
+        EXPECT_EQ(OK, factory->getDescriptor(i, &desc));
+        EXPECT_EQ(OK, factory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
+                                            1 /* deviceId */, &interface));
+    }
+}
+
+TEST(libAudioHalTest, getHalVersion) {
+    auto factory = EffectsFactoryHalInterface::create();
+    ASSERT_NE(nullptr, factory);
+
+    auto version = factory->getHalVersion();
+    EXPECT_NE(0, version.getMajorVersion());
+}
+
+class EffectParamCombination {
+  public:
+    template <typename P, typename V>
+    void init(const P& p, const V& v, size_t len) {
+        setBuffer.resize(sizeof(effect_param_t) + sizeof(p) + sizeof(v) + 4);
+        getBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
+        expectBuffer.resize(sizeof(effect_param_t) + sizeof(p) + len + 4);
+        parameterSet =
+                std::make_shared<EffectParamReader>(createEffectParam(setBuffer.data(), p, v));
+        parameterGet =
+                std::make_shared<EffectParamReader>(createEffectParam(getBuffer.data(), p, v));
+        parameterExpect =
+                std::make_shared<EffectParamReader>(createEffectParam(expectBuffer.data(), p, v));
+        valueSize = len;
+    }
+
+    std::shared_ptr<EffectParamReader> parameterSet; /* setParameter */
+    std::shared_ptr<EffectParamReader> parameterGet; /* getParameter */
+    std::shared_ptr<EffectParamReader> parameterExpect; /* expected from getParameter */
+    size_t valueSize;   /* ValueSize expect to write in reply data buffer */
+
+  private:
+    std::vector<uint8_t> setBuffer;
+    std::vector<uint8_t> getBuffer;
+    std::vector<uint8_t> expectBuffer;
+
+    template <typename P, typename V>
+    EffectParamReader createEffectParam(void* buf, const P& p, const V& v) {
+        effect_param_t* paramRet = (effect_param_t*)buf;
+        paramRet->psize = sizeof(P);
+        paramRet->vsize = sizeof(V);
+        EffectParamWriter writer(*paramRet);
+        EXPECT_EQ(OK, writer.writeToParameter(&p));
+        EXPECT_EQ(OK, writer.writeToValue(&v));
+        writer.finishValueWrite();
+        return writer;
+    }
+};
+
+template <typename P, typename V>
+std::shared_ptr<EffectParamCombination> createEffectParamCombination(const P& p, const V& v,
+                                                                     size_t len) {
+    auto comb = std::make_shared<EffectParamCombination>();
+    comb->init(p, v, len);
+    return comb;
+}
+
+enum ParamName { TUPLE_UUID, TUPLE_PARAM_COMBINATION };
+using EffectParamTestTuple =
+        std::tuple<const effect_uuid_t* /* type UUID */, std::shared_ptr<EffectParamCombination>>;
+
+static const effect_uuid_t EXTEND_EFFECT_TYPE_UUID = {
+        0xfa81dbde, 0x588b, 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+std::vector<EffectParamTestTuple> testPairs = {
+        std::make_tuple(FX_IID_AEC,
+                        createEffectParamCombination(AEC_PARAM_ECHO_DELAY, 0xff /* echoDelayMs */,
+                                                     sizeof(int32_t) /* returnValueSize */)),
+        std::make_tuple(FX_IID_AGC,
+                        createEffectParamCombination(AGC_PARAM_TARGET_LEVEL, 20 /* targetLevel */,
+                                                     sizeof(int16_t) /* returnValueSize */)),
+        std::make_tuple(FX_IID_AGC2, createEffectParamCombination(
+                                             AGC2_PARAM_FIXED_DIGITAL_GAIN, 15 /* digitalGainDb */,
+                                             sizeof(int32_t) /* returnValueSize */)),
+        std::make_tuple(SL_IID_BASSBOOST,
+                        createEffectParamCombination(BASSBOOST_PARAM_STRENGTH, 20 /* strength */,
+                                                     sizeof(int32_t) /* returnValueSize */)),
+        std::make_tuple(EFFECT_UIID_DOWNMIX,
+                        createEffectParamCombination(DOWNMIX_PARAM_TYPE, DOWNMIX_TYPE_FOLD,
+                                                     sizeof(int16_t) /* returnValueSize */)),
+        std::make_tuple(SL_IID_DYNAMICSPROCESSING,
+                        createEffectParamCombination(
+                                std::array<uint32_t, 2>({DP_PARAM_INPUT_GAIN, 0 /* channel */}),
+                                30 /* gainDb */, sizeof(int32_t) /* returnValueSize */)),
+        std::make_tuple(
+                FX_IID_HAPTICGENERATOR,
+                createEffectParamCombination(
+                        HG_PARAM_HAPTIC_INTENSITY,
+                        std::array<uint32_t, 2>(
+                                {1, uint32_t(::android::os::HapticScale::HIGH) /* scale */}),
+                        0 /* returnValueSize */)),
+        std::make_tuple(
+                FX_IID_LOUDNESS_ENHANCER,
+                createEffectParamCombination(LOUDNESS_ENHANCER_PARAM_TARGET_GAIN_MB, 5 /* gain */,
+                                             sizeof(int32_t) /* returnValueSize */)),
+        std::make_tuple(FX_IID_NS,
+                        createEffectParamCombination(NS_PARAM_LEVEL, 1 /* level */,
+                                                     sizeof(int32_t) /* returnValueSize */)),
+        std::make_tuple(&EXTEND_EFFECT_TYPE_UUID,
+                        createEffectParamCombination(1, 0xbead, sizeof(int32_t)))};
+
+class libAudioHalEffectParamTest : public ::testing::TestWithParam<EffectParamTestTuple> {
+  public:
+    libAudioHalEffectParamTest()
+        : mParamTuple(GetParam()),
+          mFactory(EffectsFactoryHalInterface::create()),
+          mTypeUuid(std::get<TUPLE_UUID>(mParamTuple)),
+          mCombination(std::get<TUPLE_PARAM_COMBINATION>(mParamTuple)),
+          mExpectedValue([&]() {
+              std::vector<uint8_t> expectData(mCombination->valueSize);
+              mCombination->parameterExpect->readFromValue(expectData.data(),
+                                                           mCombination->valueSize);
+              return expectData;
+          }()),
+          mDescs([&]() {
+              std::vector<effect_descriptor_t> descs;
+              if (mFactory && mTypeUuid && OK == mFactory->getDescriptors(mTypeUuid, &descs)) {
+                  return descs;
+              }
+              return descs;
+          }()) {}
+
+    void SetUp() override {
+        ASSERT_NE(0ul, mDescs.size());
+        for (const auto& desc : mDescs) {
+            sp<EffectHalInterface> interface = createEffectHal(desc);
+            ASSERT_NE(nullptr, interface);
+            mHalInterfaces.push_back(interface);
+        }
+    }
+
+    void initEffect(const sp<EffectHalInterface>& interface) {
+        uint32_t initReply = 0;
+        uint32_t initReplySize = sizeof(initReply);
+        ASSERT_EQ(OK, interface->command(EFFECT_CMD_INIT, 0, nullptr, &initReplySize, &initReply));
+    }
+
+    void TearDown() override {
+        for (auto& interface : mHalInterfaces) {
+            interface->close();
+        }
+    }
+
+    sp<EffectHalInterface> createEffectHal(const effect_descriptor_t& desc) {
+        sp<EffectHalInterface> interface = nullptr;
+        if (0 == std::memcmp(&desc.type, mTypeUuid, sizeof(effect_uuid_t)) &&
+            OK == mFactory->createEffect(&desc.uuid, 1 /* sessionId */, 1 /* ioId */,
+                                         1 /* deviceId */, &interface)) {
+            return interface;
+        }
+        return nullptr;
+    }
+
+    void setAndGetParameter(const sp<EffectHalInterface>& interface) {
+        uint32_t replySize = sizeof(uint32_t);
+        uint8_t reply[replySize];
+        auto parameterSet = mCombination->parameterSet;
+        ASSERT_EQ(OK,
+                  interface->command(EFFECT_CMD_SET_PARAM, (uint32_t)parameterSet->getTotalSize(),
+                                     const_cast<effect_param_t*>(&parameterSet->getEffectParam()),
+                                     &replySize, &reply))
+                << parameterSet->toString();
+        ASSERT_EQ(replySize, sizeof(uint32_t));
+
+        effect_param_t* getParam =
+                const_cast<effect_param_t*>(&mCombination->parameterGet->getEffectParam());
+        size_t maxReplySize = mCombination->valueSize + sizeof(effect_param_t) +
+                              sizeof(parameterSet->getPaddedParameterSize());
+        replySize = maxReplySize;
+        EXPECT_EQ(OK,
+                  interface->command(EFFECT_CMD_GET_PARAM, (uint32_t)parameterSet->getTotalSize(),
+                                     const_cast<effect_param_t*>(&parameterSet->getEffectParam()),
+                                     &replySize, getParam));
+        EffectParamReader parameterGet(*getParam);
+        EXPECT_EQ(replySize, parameterGet.getTotalSize()) << parameterGet.toString();
+        if (mCombination->valueSize) {
+            std::vector<uint8_t> response(mCombination->valueSize);
+            EXPECT_EQ(OK, parameterGet.readFromValue(response.data(), mCombination->valueSize))
+                    << " try get valueSize " << mCombination->valueSize << " from "
+                    << parameterGet.toString();
+            EXPECT_EQ(response, mExpectedValue);
+        }
+    }
+
+    const EffectParamTestTuple mParamTuple;
+    const sp<EffectsFactoryHalInterface> mFactory;
+    const effect_uuid_t* mTypeUuid;
+    std::shared_ptr<EffectParamCombination> mCombination;
+    const std::vector<uint8_t> mExpectedValue;
+    const std::vector<effect_descriptor_t> mDescs;
+    std::vector<sp<EffectHalInterface>> mHalInterfaces;
+};
+
+TEST_P(libAudioHalEffectParamTest, setAndGetParam) {
+    for (auto& interface : mHalInterfaces) {
+        EXPECT_NO_FATAL_FAILURE(initEffect(interface));
+        EXPECT_NO_FATAL_FAILURE(setAndGetParameter(interface));
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        libAudioHalEffectParamTest, libAudioHalEffectParamTest, ::testing::ValuesIn(testPairs),
+        [](const testing::TestParamInfo<libAudioHalEffectParamTest::ParamType>& info) {
+            AudioUuid uuid = ::aidl::android::legacy2aidl_audio_uuid_t_AudioUuid(
+                                     *std::get<TUPLE_UUID>(info.param))
+                                     .value();
+            std::string name = "UUID_" + uuid.toString();
+            std::replace_if(
+                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+            return name;
+        });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(libAudioHalEffectParamTest);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
+
+// TODO: b/263986405 Add multi-thread testing
+
+} // namespace android
diff --git a/media/libaudioprocessing/tests/test-resampler.cpp b/media/libaudioprocessing/tests/test-resampler.cpp
index f178bde..2166a83 100644
--- a/media/libaudioprocessing/tests/test-resampler.cpp
+++ b/media/libaudioprocessing/tests/test-resampler.cpp
@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <fcntl.h>
+#include <memory>
 #include <string.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
@@ -474,7 +475,7 @@
     // mono takes left channel only (out of stereo output pair)
     // stereo and multichannel preserve all channels.
     int32_t* out = (int32_t*) output_vaddr;
-    int16_t* convert = (int16_t*) malloc(output_frames * channels * sizeof(int16_t));
+    std::unique_ptr<int16_t[]> convert(new int16_t[output_frames * channels]);
 
     const int volumeShift = 12; // shift requirement for Q4.27 to Q.15
     // round to half towards zero and saturate at int16 (non-dithered)
@@ -509,7 +510,7 @@
         perror(file_out);
         return EXIT_FAILURE;
     }
-    (void) sf_writef_short(sf, convert, output_frames);
+    (void) sf_writef_short(sf, convert.get(), output_frames);
     sf_close(sf);
 
     return EXIT_SUCCESS;
diff --git a/media/libeffects/downmix/Android.bp b/media/libeffects/downmix/Android.bp
index abe622d..a5259aa 100644
--- a/media/libeffects/downmix/Android.bp
+++ b/media/libeffects/downmix/Android.bp
@@ -47,3 +47,30 @@
         "libhardware_headers",
     ],
 }
+
+cc_library_shared {
+    name: "libdownmixaidl",
+    srcs: [
+        "aidl/EffectDownmix.cpp",
+        "aidl/DownmixContext.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers"
+    ],
+    shared_libs: [
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/downmix/aidl/DownmixContext.cpp b/media/libeffects/downmix/aidl/DownmixContext.cpp
new file mode 100644
index 0000000..ac893d8
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DownmixContext"
+
+#include <android-base/logging.h>
+
+#include "DownmixContext.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::common::getChannelCount;
+using aidl::android::media::audio::common::AudioChannelLayout;
+
+namespace aidl::android::hardware::audio::effect {
+
+DownmixContext::DownmixContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    mState = DOWNMIX_STATE_UNINITIALIZED;
+    init_params(common);
+}
+
+DownmixContext::~DownmixContext() {
+    LOG(DEBUG) << __func__;
+    mState = DOWNMIX_STATE_UNINITIALIZED;
+}
+
+RetCode DownmixContext::enable() {
+    LOG(DEBUG) << __func__;
+    if (mState != DOWNMIX_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = DOWNMIX_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode DownmixContext::disable() {
+    LOG(DEBUG) << __func__;
+    if (mState != DOWNMIX_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = DOWNMIX_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void DownmixContext::reset() {
+    LOG(DEBUG) << __func__;
+    disable();
+    resetBuffer();
+}
+
+IEffect::Status DownmixContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+    IEffect::Status status = {EX_ILLEGAL_ARGUMENT, 0, 0};
+
+    if (in == nullptr || out == nullptr || getInputFrameSize() != getOutputFrameSize() ||
+        getInputFrameSize() == 0) {
+        return status;
+    }
+
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    if (mState == DOWNMIX_STATE_UNINITIALIZED) {
+        LOG(ERROR) << __func__ << "Trying to use an uninitialized downmixer";
+        return status;
+    } else if (mState == DOWNMIX_STATE_INITIALIZED) {
+        LOG(ERROR) << __func__ << "Trying to use a non-configured downmixer";
+        return status;
+    }
+
+    LOG(DEBUG) << __func__ << " start processing";
+    bool accumulate = false;
+    int frames = samples * sizeof(float) / getInputFrameSize();
+    if (mType == Downmix::Type::STRIP) {
+        int inputChannelCount = getChannelCount(mChMask);
+        while (frames) {
+            if (accumulate) {
+                out[0] = std::clamp(out[0] + in[0], -1.f, 1.f);
+                out[1] = std::clamp(out[1] + in[1], -1.f, 1.f);
+            } else {
+                out[0] = in[0];
+                out[1] = in[1];
+            }
+            in += inputChannelCount;
+            out += 2;
+            frames--;
+        }
+    } else {
+        int chMask = mChMask.get<AudioChannelLayout::layoutMask>();
+        if (!mChannelMix.process(in, out, frames, accumulate, (audio_channel_mask_t)chMask)) {
+            LOG(ERROR) << "Multichannel configuration " << mChMask.toString()
+                       << " is not supported";
+            return status;
+        }
+    }
+    LOG(DEBUG) << __func__ << " done processing";
+    return {STATUS_OK, samples, samples};
+}
+
+void DownmixContext::init_params(const Parameter::Common& common) {
+    // when configuring the effect, do not allow a blank or unsupported channel mask
+    AudioChannelLayout channelMask = common.input.base.channelMask;
+    if (isChannelMaskValid(channelMask)) {
+        LOG(ERROR) << "Downmix_Configure error: input channel mask " << channelMask.toString()
+                   << " not supported";
+    } else {
+        mType = Downmix::Type::FOLD;
+        mChMask = channelMask;
+        mState = DOWNMIX_STATE_INITIALIZED;
+    }
+}
+
+bool DownmixContext::isChannelMaskValid(AudioChannelLayout channelMask) {
+    if (channelMask.getTag() == AudioChannelLayout::layoutMask) return false;
+    int chMask = channelMask.get<AudioChannelLayout::layoutMask>();
+    // check against unsupported channels (up to FCC_26)
+    constexpr uint32_t MAXIMUM_CHANNEL_MASK = AudioChannelLayout::LAYOUT_22POINT2 |
+                                              AudioChannelLayout::CHANNEL_FRONT_WIDE_LEFT |
+                                              AudioChannelLayout::CHANNEL_FRONT_WIDE_RIGHT;
+    if (chMask & ~MAXIMUM_CHANNEL_MASK) {
+        LOG(ERROR) << "Unsupported channels in " << (chMask & ~MAXIMUM_CHANNEL_MASK);
+        return false;
+    }
+    return true;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/DownmixContext.h b/media/libeffects/downmix/aidl/DownmixContext.h
new file mode 100644
index 0000000..9a9f2da
--- /dev/null
+++ b/media/libeffects/downmix/aidl/DownmixContext.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "effect-impl/EffectContext.h"
+
+#include <audio_utils/ChannelMix.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+enum DownmixState {
+    DOWNMIX_STATE_UNINITIALIZED,
+    DOWNMIX_STATE_INITIALIZED,
+    DOWNMIX_STATE_ACTIVE,
+};
+
+class DownmixContext final : public EffectContext {
+  public:
+    DownmixContext(int statusDepth, const Parameter::Common& common);
+    ~DownmixContext();
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    RetCode setDmType(Downmix::Type type) {
+        mType = type;
+        return RetCode::SUCCESS;
+    }
+    Downmix::Type getDmType() const { return mType; }
+
+    RetCode setOutputDevice(
+            const std::vector<::aidl::android::media::audio::common::AudioDeviceDescription>&
+                    device) override {
+        // FIXME change type if playing on headset vs speaker
+        mOutputDevice = device;
+        return RetCode::SUCCESS;
+    }
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    DownmixState mState;
+    Downmix::Type mType;
+    ::aidl::android::media::audio::common::AudioChannelLayout mChMask;
+    ::android::audio_utils::channels::ChannelMix mChannelMix;
+
+    // Common Params
+    void init_params(const Parameter::Common& common);
+    bool isChannelMaskValid(::aidl::android::media::audio::common::AudioChannelLayout channelMask);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.cpp b/media/libeffects/downmix/aidl/EffectDownmix.cpp
new file mode 100644
index 0000000..7068c5c
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DownmixImpl"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "EffectDownmix.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DownmixImpl;
+using aidl::android::hardware::audio::effect::getEffectImplUuidDownmix;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDownmix()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<DownmixImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDownmix()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = DownmixImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DownmixImpl::kEffectName = "Multichannel Downmix To Stereo";
+const Descriptor DownmixImpl::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidDownmix(),
+                          .uuid = getEffectImplUuidDownmix(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+                   .name = DownmixImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus DownmixImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DownmixImpl::setParameterCommon(const Parameter& param) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = param.getTag();
+    switch (tag) {
+        case Parameter::common:
+            RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setCommFailed");
+            break;
+        case Parameter::deviceDescription:
+            RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+            break;
+        case Parameter::mode:
+            RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setModeFailed");
+            break;
+        case Parameter::source:
+            RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+            break;
+        case Parameter::volumeStereo:
+            RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+            break;
+        default: {
+            LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commonParamNotSupported");
+        }
+    }
+    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");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& dmParam = specific.get<Parameter::Specific::downmix>();
+    auto tag = dmParam.getTag();
+
+    switch (tag) {
+        case Downmix::type: {
+            RETURN_IF(mContext->setDmType(dmParam.get<Downmix::type>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setTypeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterSpecific(const Parameter::Id& id,
+                                                     Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::downmixTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto dmId = id.get<Parameter::Id::downmixTag>();
+    auto dmIdTag = dmId.getTag();
+    switch (dmIdTag) {
+        case Downmix::Id::commonTag:
+            return getParameterDownmix(dmId.get<Downmix::Id::commonTag>(), specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(dmIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus DownmixImpl::getParameterDownmix(const Downmix::Tag& tag,
+                                                    Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    Downmix dmParam;
+    switch (tag) {
+        case Downmix::type: {
+            dmParam.set<Downmix::type>(mContext->getDmType());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "DownmixTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::downmix>(dmParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DownmixImpl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<DownmixContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode DownmixImpl::releaseContext() {
+    if (mContext) {
+        mContext.reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DownmixImpl::effectProcessImpl(float* in, float* out, int sampleToProcess) {
+    if (!mContext) {
+        LOG(ERROR) << __func__ << " nullContext";
+        return {EX_NULL_POINTER, 0, 0};
+    }
+    return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/downmix/aidl/EffectDownmix.h b/media/libeffects/downmix/aidl/EffectDownmix.h
new file mode 100644
index 0000000..812d26b
--- /dev/null
+++ b/media/libeffects/downmix/aidl/EffectDownmix.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <audio_effects/effect_downmix.h>
+
+#include "DownmixContext.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DownmixImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    DownmixImpl() { LOG(DEBUG) << __func__; }
+    ~DownmixImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<DownmixContext> mContext;
+    ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/Android.bp b/media/libeffects/dynamicsproc/Android.bp
index 84131a4..736a086 100644
--- a/media/libeffects/dynamicsproc/Android.bp
+++ b/media/libeffects/dynamicsproc/Android.bp
@@ -32,34 +32,67 @@
     ],
 }
 
+cc_defaults {
+    name : "dynamicsprocessingdefaults",
+    srcs: [
+        "dsp/DPBase.cpp",
+        "dsp/DPFrequency.cpp",
+    ],
+
+    shared_libs: [
+        "libaudioutils",
+        "libbase",
+        "liblog",
+        "libutils",
+    ],
+    header_libs: [
+        "libaudioeffects",
+        "libeigen",
+    ],
+    cflags: [
+        "-Wthread-safety",
+        "-Wall",
+        "-Werror",
+    ],
+    relative_install_path: "soundfx",
+}
+
 cc_library_shared {
     name: "libdynproc",
 
     vendor: true,
 
+    defaults: [
+        "dynamicsprocessingdefaults",
+    ],
+
     srcs: [
         "EffectDynamicsProcessing.cpp",
-        "dsp/DPBase.cpp",
-        "dsp/DPFrequency.cpp",
     ],
 
     cflags: [
         "-O2",
         "-fvisibility=hidden",
+    ],
+}
 
-        "-Wall",
-        "-Werror",
+cc_library_shared {
+    name: "libdynamicsprocessingaidl",
+
+    srcs: [
+        "aidl/DynamicsProcessing.cpp",
+        "aidl/DynamicsProcessingContext.cpp",
+        ":effectCommonFile",
     ],
 
-    shared_libs: [
-        "libcutils",
-        "liblog",
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "dynamicsprocessingdefaults",
     ],
 
-    relative_install_path: "soundfx",
-
-    header_libs: [
-        "libaudioeffects",
-        "libeigen",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
     ],
 }
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
new file mode 100644
index 0000000..e508d48
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.cpp
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DynamicsProcessingLibEffects"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "DynamicsProcessing.h"
+
+#include <dsp/DPBase.h>
+#include <dsp/DPFrequency.h>
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::DynamicsProcessingImpl;
+using aidl::android::hardware::audio::effect::getEffectImplUuidDynamicsProcessing;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::media::audio::common::PcmType;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDynamicsProcessing()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<DynamicsProcessingImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidDynamicsProcessing()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = DynamicsProcessingImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string DynamicsProcessingImpl::kEffectName = "DynamicsProcessing";
+
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMin =
+        DynamicsProcessing::EqBandConfig({.channel = 0,
+                                          .band = 0,
+                                          .enable = false,
+                                          .cutoffFrequencyHz = 220,
+                                          .gainDb = std::numeric_limits<float>::min()});
+const DynamicsProcessing::EqBandConfig DynamicsProcessingImpl::kEqBandConfigMax =
+        DynamicsProcessing::EqBandConfig({.channel = std::numeric_limits<int>::max(),
+                                          .band = std::numeric_limits<int>::max(),
+                                          .enable = true,
+                                          .cutoffFrequencyHz = 20000,
+                                          .gainDb = std::numeric_limits<float>::max()});
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPreEqBandRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range::DynamicsProcessingRange DynamicsProcessingImpl::kPostEqBandRange = {
+        .min = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMin}),
+        .max = DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                {DynamicsProcessingImpl::kEqBandConfigMax})};
+const Range DynamicsProcessingImpl::kRange =
+        Range::make<Range::dynamicsProcessing>({DynamicsProcessingImpl::kPreEqBandRange});
+
+const Capability DynamicsProcessingImpl::kCapability = {.range = {DynamicsProcessingImpl::kRange}};
+
+const Descriptor DynamicsProcessingImpl::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidDynamicsProcessing(),
+                          .uuid = getEffectImplUuidDynamicsProcessing(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = DynamicsProcessingImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = DynamicsProcessingImpl::kCapability};
+
+ndk::ScopedAStatus DynamicsProcessingImpl::open(const Parameter::Common& common,
+                                                const std::optional<Parameter::Specific>& specific,
+                                                OpenEffectReturn* ret) {
+    LOG(DEBUG) << __func__;
+    // effect only support 32bits float
+    RETURN_IF(common.input.base.format.pcm != common.output.base.format.pcm ||
+                      common.input.base.format.pcm != PcmType::FLOAT_32_BIT,
+              EX_ILLEGAL_ARGUMENT, "dataMustBe32BitsFloat");
+    RETURN_OK_IF(mState != State::INIT);
+    auto context = createContext(common);
+    RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed");
+
+    RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
+    if (specific.has_value()) {
+        RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
+    } else {
+        Parameter::Specific defaultSpecific =
+                Parameter::Specific::make<Parameter::Specific::dynamicsProcessing>(
+                        DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(
+                                mContext->getEngineArchitecture()));
+        RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(defaultSpecific), "setDefaultEngineErr");
+    }
+
+    mState = State::IDLE;
+    context->dupeFmq(ret);
+    RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+              "FailedToCreateWorker");
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    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");
+    }
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::setParameterSpecific(
+        const Parameter::Specific& specific) {
+    RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+              "EffectNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& param = specific.get<Parameter::Specific::dynamicsProcessing>();
+    // TODO: check range here, dynamicsProcessing need customized method for nested parameters.
+    auto tag = param.getTag();
+
+    switch (tag) {
+        case DynamicsProcessing::engineArchitecture: {
+            RETURN_IF(mContext->setEngineArchitecture(
+                              param.get<DynamicsProcessing::engineArchitecture>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setEngineArchitectureFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::preEq: {
+            RETURN_IF(
+                    mContext->setPreEq(param.get<DynamicsProcessing::preEq>()) != RetCode::SUCCESS,
+                    EX_ILLEGAL_ARGUMENT, "setPreEqFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::postEq: {
+            RETURN_IF(mContext->setPostEq(param.get<DynamicsProcessing::postEq>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setPostEqFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::preEqBand: {
+            RETURN_IF(mContext->setPreEqBand(param.get<DynamicsProcessing::preEqBand>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setPreEqBandFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::postEqBand: {
+            RETURN_IF(mContext->setPostEqBand(param.get<DynamicsProcessing::postEqBand>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setPostEqBandFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::mbc: {
+            RETURN_IF(mContext->setMbc(param.get<DynamicsProcessing::mbc>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setMbcFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::mbcBand: {
+            RETURN_IF(mContext->setMbcBand(param.get<DynamicsProcessing::mbcBand>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setMbcBandFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::limiter: {
+            RETURN_IF(mContext->setLimiter(param.get<DynamicsProcessing::limiter>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLimiterFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::inputGain: {
+            RETURN_IF(mContext->setInputGain(param.get<DynamicsProcessing::inputGain>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setInputGainFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::vendor: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "DPVendorExtensionTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::getParameterSpecific(const Parameter::Id& id,
+                                                                Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto dpId = id.get<Parameter::Id::dynamicsProcessingTag>();
+    auto dpIdTag = dpId.getTag();
+    switch (dpIdTag) {
+        case DynamicsProcessing::Id::commonTag:
+            return getParameterDynamicsProcessing(dpId.get<DynamicsProcessing::Id::commonTag>(),
+                                                  specific);
+        case DynamicsProcessing::Id::vendorExtensionTag:
+            LOG(ERROR) << __func__ << " unsupported ID: " << toString(dpIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "DPVendorExtensionIdNotSupported");
+    }
+}
+
+ndk::ScopedAStatus DynamicsProcessingImpl::getParameterDynamicsProcessing(
+        const DynamicsProcessing::Tag& tag, Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    switch (tag) {
+        case DynamicsProcessing::engineArchitecture: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::engineArchitecture>(
+                            mContext->getEngineArchitecture()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::preEq: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::preEq>(mContext->getPreEq()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::postEq: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::postEq>(mContext->getPostEq()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::preEqBand: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::preEqBand>(
+                            mContext->getPreEqBand()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::postEqBand: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::postEqBand>(
+                            mContext->getPostEqBand()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::mbc: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::mbc>(mContext->getMbc()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::mbcBand: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::mbcBand>(mContext->getMbcBand()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::limiter: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::limiter>(mContext->getLimiter()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::inputGain: {
+            specific->set<Parameter::Specific::dynamicsProcessing>(
+                    DynamicsProcessing::make<DynamicsProcessing::inputGain>(
+                            mContext->getInputGain()));
+            return ndk::ScopedAStatus::ok();
+        }
+        case DynamicsProcessing::vendor: {
+            LOG(ERROR) << __func__ << " wrong vendor tag in CommonTag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "DPVendorExtensionTagInWrongId");
+        }
+    }
+}
+
+std::shared_ptr<EffectContext> DynamicsProcessingImpl::createContext(
+        const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<DynamicsProcessingContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode DynamicsProcessingImpl::releaseContext() {
+    if (mContext) {
+        mContext->disable();
+        mContext->resetBuffer();
+        mContext.reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DynamicsProcessingImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
new file mode 100644
index 0000000..d094c69
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessing.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "DynamicsProcessingContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DynamicsProcessingImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    static const Capability kCapability;
+
+    DynamicsProcessingImpl() { LOG(DEBUG) << __func__; }
+    ~DynamicsProcessingImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus open(const Parameter::Common& common,
+                            const std::optional<Parameter::Specific>& specific,
+                            OpenEffectReturn* ret) override;
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    static const DynamicsProcessing::EqBandConfig kEqBandConfigMin;
+    static const DynamicsProcessing::EqBandConfig kEqBandConfigMax;
+    static const Range::DynamicsProcessingRange kPreEqBandRange;
+    static const Range::DynamicsProcessingRange kPostEqBandRange;
+    static const Range kRange;
+    std::shared_ptr<DynamicsProcessingContext> mContext;
+    ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
+                                                      Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
new file mode 100644
index 0000000..69ff522
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.cpp
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_DPLibEffectsContext"
+
+#include "DynamicsProcessing.h"
+#include "DynamicsProcessingContext.h"
+
+#include <functional>
+#include <sys/param.h>
+#include <unordered_set>
+
+namespace aidl::android::hardware::audio::effect {
+
+DynamicsProcessingContext::DynamicsProcessingContext(int statusDepth,
+                                                     const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    init();
+}
+
+DynamicsProcessingContext::~DynamicsProcessingContext() {
+    LOG(DEBUG) << __func__;
+}
+
+RetCode DynamicsProcessingContext::enable() {
+    std::lock_guard lg(mMutex);
+    if (mState != DYNAMICS_PROCESSING_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = DYNAMICS_PROCESSING_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode DynamicsProcessingContext::disable() {
+    std::lock_guard lg(mMutex);
+    if (mState != DYNAMICS_PROCESSING_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void DynamicsProcessingContext::reset() {
+    std::lock_guard lg(mMutex);
+    if (mDpFreq != nullptr) {
+        mDpFreq.reset();
+    }
+}
+
+RetCode DynamicsProcessingContext::setCommon(const Parameter::Common& common) {
+    mCommon = common;
+    init();
+    LOG(INFO) << __func__ << common.toString();
+    return RetCode::SUCCESS;
+}
+
+void DynamicsProcessingContext::dpSetFreqDomainVariant_l(
+        const DynamicsProcessing::EngineArchitecture& engine) {
+    mDpFreq.reset(new dp_fx::DPFrequency());
+    mDpFreq->init(mChannelCount, engine.preEqStage.inUse, engine.preEqStage.bandCount,
+                  engine.mbcStage.inUse, engine.mbcStage.bandCount, engine.postEqStage.inUse,
+                  engine.postEqStage.bandCount, engine.limiterInUse);
+
+    int32_t sampleRate = mCommon.input.base.sampleRate;
+    int32_t minBlockSize = (int32_t)dp_fx::DPFrequency::getMinBockSize();
+    int32_t block = engine.preferredProcessingDurationMs * sampleRate / 1000.0f;
+    LOG(INFO) << __func__ << " sampleRate " << sampleRate << " block length "
+              << engine.preferredProcessingDurationMs << " ms (" << block << "samples)";
+    if (block < minBlockSize) {
+        block = minBlockSize;
+    } else if (!powerof2(block)) {
+        //find next highest power of 2.
+        block = 1 << (32 - __builtin_clz(block));
+    }
+    mDpFreq->configure(block, block >> 1, sampleRate);
+}
+
+RetCode DynamicsProcessingContext::setEngineArchitecture(
+        const DynamicsProcessing::EngineArchitecture& engineArchitecture) {
+    RETURN_VALUE_IF(!validateEngineConfig(engineArchitecture), RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "illegalEngineConfig");
+
+    std::lock_guard lg(mMutex);
+    if (!mEngineInited || mEngineArchitecture != engineArchitecture) {
+        if (engineArchitecture.resolutionPreference ==
+            DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION) {
+            dpSetFreqDomainVariant_l(engineArchitecture);
+        } else {
+            LOG(WARNING) << __func__ << toString(engineArchitecture.resolutionPreference)
+                         << " not available now";
+        }
+        mEngineInited = true;
+        mEngineArchitecture = engineArchitecture;
+    }
+    LOG(INFO) << __func__ << engineArchitecture.toString();
+    return RetCode::SUCCESS;
+}
+
+RetCode DynamicsProcessingContext::setPreEq(
+        const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
+    std::lock_guard lg(mMutex);
+    return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.preEqStage.inUse,
+                                        StageType::PREEQ);
+}
+
+RetCode DynamicsProcessingContext::setPostEq(
+        const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
+    std::lock_guard lg(mMutex);
+    return setDpChannels_l<dp_fx::DPEq>(channels, mEngineArchitecture.postEqStage.inUse,
+                                        StageType::POSTEQ);
+}
+
+RetCode DynamicsProcessingContext::setMbc(
+        const std::vector<DynamicsProcessing::ChannelConfig>& channels) {
+    std::lock_guard lg(mMutex);
+    return setDpChannels_l<dp_fx::DPMbc>(channels, mEngineArchitecture.mbcStage.inUse,
+                                         StageType::MBC);
+}
+
+RetCode DynamicsProcessingContext::setPreEqBand(
+        const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
+    std::lock_guard lg(mMutex);
+    RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "postEqNotInUse");
+    return setBands_l<DynamicsProcessing::EqBandConfig>(
+            bands, mEngineArchitecture.preEqStage.bandCount, StageType::PREEQ);
+}
+
+RetCode DynamicsProcessingContext::setPostEqBand(
+        const std::vector<DynamicsProcessing::EqBandConfig>& bands) {
+    std::lock_guard lg(mMutex);
+    RETURN_VALUE_IF(!mEngineArchitecture.postEqStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "postEqNotInUse");
+    return setBands_l<DynamicsProcessing::EqBandConfig>(
+            bands, mEngineArchitecture.postEqStage.bandCount, StageType::POSTEQ);
+}
+
+RetCode DynamicsProcessingContext::setMbcBand(
+        const std::vector<DynamicsProcessing::MbcBandConfig>& bands) {
+    std::lock_guard lg(mMutex);
+    RETURN_VALUE_IF(!mEngineArchitecture.mbcStage.inUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "mbcNotInUse");
+    return setBands_l<DynamicsProcessing::MbcBandConfig>(
+            bands, mEngineArchitecture.preEqStage.bandCount, StageType::MBC);
+}
+
+RetCode DynamicsProcessingContext::setLimiter(
+        const std::vector<DynamicsProcessing::LimiterConfig>& limiters) {
+    std::lock_guard lg(mMutex);
+    RETURN_VALUE_IF(!mEngineArchitecture.limiterInUse, RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "limiterNotInUse");
+    return setBands_l<DynamicsProcessing::LimiterConfig>(limiters, -1, StageType::LIMITER);
+}
+
+RetCode DynamicsProcessingContext::setInputGain(
+        const std::vector<DynamicsProcessing::InputGain>& inputGains) {
+    std::lock_guard lg(mMutex);
+    return setBands_l<DynamicsProcessing::InputGain>(inputGains, -1, StageType::INPUTGAIN);
+}
+
+DynamicsProcessing::EngineArchitecture DynamicsProcessingContext::getEngineArchitecture() {
+    std::lock_guard lg(mMutex);
+    LOG(INFO) << __func__ << mEngineArchitecture.toString();
+    return mEngineArchitecture;
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPreEq() {
+    return getChannelConfig(StageType::PREEQ);
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getPostEq() {
+    return getChannelConfig(StageType::POSTEQ);
+}
+
+std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPreEqBand() {
+    return getEqBandConfigs(StageType::PREEQ);
+}
+
+std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getPostEqBand() {
+    return getEqBandConfigs(StageType::POSTEQ);
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getMbc() {
+    return getChannelConfig(StageType::MBC);
+}
+
+std::vector<DynamicsProcessing::MbcBandConfig> DynamicsProcessingContext::getMbcBand() {
+    std::vector<DynamicsProcessing::MbcBandConfig> bands;
+
+    std::lock_guard lg(mMutex);
+    auto maxBand = mEngineArchitecture.mbcStage.bandCount;
+    for (int32_t ch = 0; ch < mChannelCount; ch++) {
+        auto mbc = getMbc_l(ch);
+        if (!mbc) {
+            continue;
+        }
+        for (int32_t bandId = 0; bandId < maxBand; bandId++) {
+            auto band = mbc->getBand(bandId);
+            if (!band) {
+                continue;
+            }
+            bands.push_back({.channel = ch,
+                             .band = bandId,
+                             .enable = band->isEnabled(),
+                             .cutoffFrequencyHz = band->getCutoffFrequency(),
+                             .attackTimeMs = band->getAttackTime(),
+                             .releaseTimeMs = band->getReleaseTime(),
+                             .ratio = band->getRatio(),
+                             .thresholdDb = band->getThreshold(),
+                             .kneeWidthDb = band->getKneeWidth(),
+                             .noiseGateThresholdDb = band->getNoiseGateThreshold(),
+                             .expanderRatio = band->getExpanderRatio(),
+                             .preGainDb = band->getPreGain(),
+                             .postGainDb = band->getPostGain()});
+        }
+    }
+    return bands;
+}
+
+std::vector<DynamicsProcessing::LimiterConfig> DynamicsProcessingContext::getLimiter() {
+    std::vector<DynamicsProcessing::LimiterConfig> ret;
+
+    std::lock_guard lg(mMutex);
+    for (int32_t ch = 0; ch < mChannelCount; ch++) {
+        auto limiter = getLimiter_l(ch);
+        if (!limiter) {
+            continue;
+        }
+        ret.push_back({.channel = ch,
+                       .enable = limiter->isEnabled(),
+                       .linkGroup = static_cast<int32_t>(limiter->getLinkGroup()),
+                       .attackTimeMs = limiter->getAttackTime(),
+                       .releaseTimeMs = limiter->getReleaseTime(),
+                       .ratio = limiter->getRatio(),
+                       .thresholdDb = limiter->getThreshold(),
+                       .postGainDb = limiter->getPostGain()});
+    }
+    return ret;
+}
+
+std::vector<DynamicsProcessing::InputGain> DynamicsProcessingContext::getInputGain() {
+    std::vector<DynamicsProcessing::InputGain> ret;
+
+    std::lock_guard lg(mMutex);
+    for (int32_t ch = 0; ch < mChannelCount; ch++) {
+        auto channel = getChannel_l(ch);
+        if (!channel) {
+            continue;
+        }
+        ret.push_back({.channel = ch, .gainDb = channel->getInputGain()});
+    }
+    return ret;
+}
+
+IEffect::Status DynamicsProcessingContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+
+    LOG(DEBUG) << __func__ << " start processing";
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(mState != DynamicsProcessingState::DYNAMICS_PROCESSING_STATE_ACTIVE, status,
+                        "notInActiveState");
+        RETURN_VALUE_IF(!mDpFreq, status, "engineNotInited");
+        mDpFreq->processSamples(in, out, samples);
+    }
+    return {STATUS_OK, samples, samples};
+}
+
+void DynamicsProcessingContext::init() {
+    std::lock_guard lg(mMutex);
+    mState = DYNAMICS_PROCESSING_STATE_INITIALIZED;
+    mChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+            mCommon.input.base.channelMask);
+}
+
+dp_fx::DPChannel* DynamicsProcessingContext::getChannel_l(int channel) {
+    RETURN_VALUE_IF(mDpFreq == nullptr, nullptr, "DPFreqNotInited");
+
+    return mDpFreq->getChannel(channel);
+}
+
+dp_fx::DPEq* DynamicsProcessingContext::getPreEq_l(int ch) {
+    auto channel = getChannel_l(ch);
+    RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+    return channel->getPreEq();
+}
+
+dp_fx::DPEq* DynamicsProcessingContext::getPostEq_l(int ch) {
+    auto channel = getChannel_l(ch);
+    RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+    return channel->getPostEq();
+}
+
+dp_fx::DPMbc* DynamicsProcessingContext::getMbc_l(int ch) {
+    auto channel = getChannel_l(ch);
+    RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+    return channel->getMbc();
+}
+
+dp_fx::DPLimiter* DynamicsProcessingContext::getLimiter_l(int ch) {
+    auto channel = getChannel_l(ch);
+    RETURN_VALUE_IF(channel == nullptr, nullptr, "ChannelNotExist");
+
+    return channel->getLimiter();
+}
+
+dp_fx::DPBandStage* DynamicsProcessingContext::getStageWithType_l(
+        DynamicsProcessingContext::StageType type, int ch) {
+    switch (type) {
+        case StageType::PREEQ: {
+            return getEqWithType_l(type, ch);
+        }
+        case StageType::POSTEQ: {
+            return getEqWithType_l(type, ch);
+        }
+        case StageType::MBC: {
+            return getMbc_l(ch);
+        }
+        case StageType::LIMITER:
+            FALLTHROUGH_INTENDED;
+        case StageType::INPUTGAIN: {
+            return nullptr;
+        }
+    }
+}
+
+dp_fx::DPEq* DynamicsProcessingContext::getEqWithType_l(DynamicsProcessingContext::StageType type,
+                                                        int ch) {
+    switch (type) {
+        case StageType::PREEQ: {
+            return getPreEq_l(ch);
+        }
+        case StageType::POSTEQ: {
+            return getPostEq_l(ch);
+        }
+        case StageType::MBC:
+            FALLTHROUGH_INTENDED;
+        case StageType::LIMITER:
+            FALLTHROUGH_INTENDED;
+        case StageType::INPUTGAIN: {
+            return nullptr;
+        }
+    }
+}
+
+std::vector<DynamicsProcessing::ChannelConfig> DynamicsProcessingContext::getChannelConfig(
+        StageType type) {
+    std::vector<DynamicsProcessing::ChannelConfig> ret;
+
+    std::lock_guard lg(mMutex);
+    for (int32_t ch = 0; ch < mChannelCount; ch++) {
+        auto stage = getStageWithType_l(type, ch);
+        if (!stage) {
+            continue;
+        }
+        ret.push_back({.channel = ch, .enable = stage->isEnabled()});
+    }
+    return ret;
+}
+
+std::vector<DynamicsProcessing::EqBandConfig> DynamicsProcessingContext::getEqBandConfigs(
+        StageType type) {
+    std::vector<DynamicsProcessing::EqBandConfig> eqBands;
+
+    std::lock_guard lg(mMutex);
+    auto maxBand = mEngineArchitecture.preEqStage.bandCount;
+    for (int32_t ch = 0; ch < mChannelCount; ch++) {
+        auto eq = getEqWithType_l(type, ch);
+        if (!eq) {
+            continue;
+        }
+        for (int32_t bandId = 0; bandId < maxBand; bandId++) {
+            auto band = eq->getBand(bandId);
+            if (!band) {
+                continue;
+            }
+            eqBands.push_back({.channel = ch,
+                               .band = bandId,
+                               .enable = band->isEnabled(),
+                               .cutoffFrequencyHz = band->getCutoffFrequency(),
+                               .gainDb = band->getGain()});
+        }
+    }
+    return eqBands;
+}
+
+/**
+ * When StageEnablement is in use, bandCount needs to be positive.
+ */
+bool DynamicsProcessingContext::validateStageEnablement(
+        const DynamicsProcessing::StageEnablement& enablement) {
+    return !enablement.inUse || (enablement.inUse && enablement.bandCount > 0);
+}
+
+bool DynamicsProcessingContext::validateEngineConfig(
+        const DynamicsProcessing::EngineArchitecture& engine) {
+    return engine.preferredProcessingDurationMs >= 0 &&
+           validateStageEnablement(engine.preEqStage) &&
+           validateStageEnablement(engine.postEqStage) && validateStageEnablement(engine.mbcStage);
+}
+
+bool DynamicsProcessingContext::validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band,
+                                                     int maxChannel, int maxBand) {
+    return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand);
+}
+
+bool DynamicsProcessingContext::validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band,
+                                                      int maxChannel, int maxBand) {
+    return validateChannel(band.channel, maxChannel) && validateBand(band.band, maxBand) &&
+           validateTime(band.attackTimeMs) && validateTime(band.releaseTimeMs) &&
+           validateRatio(band.ratio) && validateBandDb(band.thresholdDb) &&
+           validateBandDb(band.kneeWidthDb) && validateBandDb(band.noiseGateThresholdDb) &&
+           validateRatio(band.expanderRatio);
+}
+
+bool DynamicsProcessingContext::validateLimiterConfig(
+        const DynamicsProcessing::LimiterConfig& limiter, int maxChannel) {
+    return validateChannel(limiter.channel, maxChannel) && validateTime(limiter.attackTimeMs) &&
+           validateTime(limiter.releaseTimeMs) && validateRatio(limiter.ratio) &&
+           validateBandDb(limiter.thresholdDb);
+}
+
+bool DynamicsProcessingContext::validateInputGainConfig(const DynamicsProcessing::InputGain& gain,
+                                                        int maxChannel) {
+    return validateChannel(gain.channel, maxChannel);
+}
+
+template <typename D>
+RetCode DynamicsProcessingContext::setDpChannels_l(
+        const std::vector<DynamicsProcessing::ChannelConfig>& channels, bool stageInUse,
+        StageType type) {
+    RetCode ret = RetCode::SUCCESS;
+    std::unordered_set<int> channelSet;
+
+    RETURN_VALUE_IF(!stageInUse, RetCode::ERROR_ILLEGAL_PARAMETER, "stageNotInUse");
+    for (auto& it : channels) {
+        if (0 != channelSet.count(it.channel)) {
+            LOG(WARNING) << __func__ << " duplicated channel " << it.channel;
+            ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+        } else {
+            channelSet.insert(it.channel);
+        }
+        if (it.channel < 0 || it.channel >= mChannelCount) {
+            LOG(WARNING) << __func__ << " skip illegal ChannelConfig " << it.toString() << " max "
+                         << mChannelCount;
+            ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+            continue;
+        }
+        auto dp = getStageWithType_l(type, it.channel);
+        if (!dp) {
+            LOG(WARNING) << __func__ << " channel " << it.channel << " not exist";
+            ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+            continue;
+        }
+        if (dp->isEnabled() != it.enable) {
+            LOG(INFO) << __func__ << it.toString();
+            dp->setEnabled(it.enable);
+        }
+    }
+    return ret;
+}
+
+RetCode DynamicsProcessingContext::setDpChannelBand_l(const std::any& anyConfig, StageType type,
+                                                      int maxCh, int maxBand,
+                                                      std::set<std::pair<int, int>>& chBandSet) {
+    RETURN_VALUE_IF(!anyConfig.has_value(), RetCode::ERROR_ILLEGAL_PARAMETER, "bandInvalid");
+    RetCode ret = RetCode::SUCCESS;
+    std::pair<int, int> chBandKey;
+    switch (type) {
+        case StageType::PREEQ:
+            FALLTHROUGH_INTENDED;
+        case StageType::POSTEQ: {
+            dp_fx::DPEq* dp;
+            const auto& config = std::any_cast<DynamicsProcessing::EqBandConfig>(anyConfig);
+            RETURN_VALUE_IF(!validateEqBandConfig(config, maxCh, maxBand),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "eqBandNotValid");
+            RETURN_VALUE_IF(
+                    nullptr == (dp = getEqWithType_l(type, config.channel)) || !dp->isEnabled(),
+                    RetCode::ERROR_ILLEGAL_PARAMETER, "dpEqNotExist");
+            dp_fx::DPEqBand band;
+            band.init(config.enable, config.cutoffFrequencyHz, config.gainDb);
+            dp->setBand(config.band, band);
+            chBandKey = {config.channel, config.band};
+            break;
+        }
+        case StageType::MBC: {
+            dp_fx::DPMbc* dp;
+            const auto& config = std::any_cast<DynamicsProcessing::MbcBandConfig>(anyConfig);
+            RETURN_VALUE_IF(!validateMbcBandConfig(config, maxCh, maxBand),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "mbcBandNotValid");
+            RETURN_VALUE_IF(nullptr == (dp = getMbc_l(config.channel)) || !dp->isEnabled(),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "dpMbcNotExist");
+            dp_fx::DPMbcBand band;
+            band.init(config.enable, config.cutoffFrequencyHz, config.attackTimeMs,
+                      config.releaseTimeMs, config.ratio, config.thresholdDb, config.kneeWidthDb,
+                      config.noiseGateThresholdDb, config.expanderRatio, config.preGainDb,
+                      config.postGainDb);
+            dp->setBand(config.band, band);
+            chBandKey = {config.channel, config.band};
+            break;
+        }
+        case StageType::LIMITER: {
+            dp_fx::DPChannel* dp;
+            const auto& config = std::any_cast<DynamicsProcessing::LimiterConfig>(anyConfig);
+            RETURN_VALUE_IF(!validateLimiterConfig(config, maxCh),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "limiterBandNotValid");
+            RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
+            dp_fx::DPLimiter limiter;
+            limiter.init(mEngineArchitecture.limiterInUse, config.enable, config.linkGroup,
+                         config.attackTimeMs, config.releaseTimeMs, config.ratio,
+                         config.thresholdDb, config.postGainDb);
+            dp->setLimiter(limiter);
+            chBandKey = {config.channel, 0};
+            break;
+        }
+        case StageType::INPUTGAIN: {
+            dp_fx::DPChannel* dp;
+            const auto& config = std::any_cast<DynamicsProcessing::InputGain>(anyConfig);
+            RETURN_VALUE_IF(!validateInputGainConfig(config, maxCh),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "inputGainNotValid");
+            RETURN_VALUE_IF(nullptr == (dp = getChannel_l(config.channel)),
+                            RetCode::ERROR_ILLEGAL_PARAMETER, "dpChNotExist");
+            dp->setInputGain(config.gainDb);
+            chBandKey = {config.channel, 0};
+            break;
+        }
+    }
+    RETURN_VALUE_IF(0 != chBandSet.count(chBandKey), RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "duplicatedBand");
+    chBandSet.insert(chBandKey);
+    return ret;
+}
+
+template <typename T /* BandConfig */>
+RetCode DynamicsProcessingContext::setBands_l(
+        const std::vector<T>& bands, int maxBand, StageType type) {
+    RetCode ret = RetCode::SUCCESS;
+    std::set<std::pair<int /* channel */, int /* band */>> bandSet;
+
+    for (const auto& it : bands) {
+        if (RetCode::SUCCESS !=
+            setDpChannelBand_l(std::make_any<T>(it), type, mChannelCount, maxBand, bandSet)) {
+            LOG(WARNING) << __func__ << " skipping band " << it.toString();
+            ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+            continue;
+        }
+        LOG(INFO) << __func__ << it.toString();
+    }
+    return ret;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
new file mode 100644
index 0000000..8be784e
--- /dev/null
+++ b/media/libeffects/dynamicsproc/aidl/DynamicsProcessingContext.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <audio_effects/effect_dynamicsprocessing.h>
+
+#include "effect-impl/EffectContext.h"
+
+#include <any>
+#include <cstddef>
+#include <dsp/DPBase.h>
+#include <dsp/DPFrequency.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+enum DynamicsProcessingState {
+    DYNAMICS_PROCESSING_STATE_UNINITIALIZED,
+    DYNAMICS_PROCESSING_STATE_INITIALIZED,
+    DYNAMICS_PROCESSING_STATE_ACTIVE,
+};
+
+class DynamicsProcessingContext final : public EffectContext {
+  public:
+    DynamicsProcessingContext(int statusDepth, const Parameter::Common& common);
+    ~DynamicsProcessingContext();
+
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    // override EffectContext::setCommon to update mChannelCount
+    RetCode setCommon(const Parameter::Common& common) override;
+
+    RetCode setEngineArchitecture(const DynamicsProcessing::EngineArchitecture& engineArchitecture);
+    RetCode setPreEq(const std::vector<DynamicsProcessing::ChannelConfig>& eqChannels);
+    RetCode setPostEq(const std::vector<DynamicsProcessing::ChannelConfig>& eqChannels);
+    RetCode setPreEqBand(const std::vector<DynamicsProcessing::EqBandConfig>& eqBands);
+    RetCode setPostEqBand(const std::vector<DynamicsProcessing::EqBandConfig>& eqBands);
+    RetCode setMbc(const std::vector<DynamicsProcessing::ChannelConfig>& mbcChannels);
+    RetCode setMbcBand(const std::vector<DynamicsProcessing::MbcBandConfig>& eqBands);
+    RetCode setLimiter(const std::vector<DynamicsProcessing::LimiterConfig>& limiters);
+    RetCode setInputGain(const std::vector<DynamicsProcessing::InputGain>& gain);
+
+    DynamicsProcessing::EngineArchitecture getEngineArchitecture();
+    std::vector<DynamicsProcessing::ChannelConfig> getPreEq();
+    std::vector<DynamicsProcessing::ChannelConfig> getPostEq();
+    std::vector<DynamicsProcessing::EqBandConfig> getPreEqBand();
+    std::vector<DynamicsProcessing::EqBandConfig> getPostEqBand();
+    std::vector<DynamicsProcessing::ChannelConfig> getMbc();
+    std::vector<DynamicsProcessing::MbcBandConfig> getMbcBand();
+    std::vector<DynamicsProcessing::LimiterConfig> getLimiter();
+    std::vector<DynamicsProcessing::InputGain> getInputGain();
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    static constexpr float kPreferredProcessingDurationMs = 10.0f;
+    static constexpr int kBandCount = 5;
+    std::mutex mMutex;
+    size_t mChannelCount GUARDED_BY(mMutex) = 0;
+    DynamicsProcessingState mState GUARDED_BY(mMutex) = DYNAMICS_PROCESSING_STATE_UNINITIALIZED;
+    std::unique_ptr<dp_fx::DPFrequency> mDpFreq GUARDED_BY(mMutex) = nullptr;
+    bool mEngineInited GUARDED_BY(mMutex) = false;
+    DynamicsProcessing::EngineArchitecture mEngineArchitecture GUARDED_BY(mMutex) = {
+            .resolutionPreference =
+                    DynamicsProcessing::ResolutionPreference::FAVOR_FREQUENCY_RESOLUTION,
+            .preferredProcessingDurationMs = kPreferredProcessingDurationMs,
+            .preEqStage = {.inUse = true, .bandCount = kBandCount},
+            .postEqStage = {.inUse = true, .bandCount = kBandCount},
+            .mbcStage = {.inUse = true, .bandCount = kBandCount},
+            .limiterInUse = true,
+    };
+
+    enum class StageType { PREEQ, POSTEQ, MBC, LIMITER, INPUTGAIN };
+
+    void init();
+
+    void dpSetFreqDomainVariant_l(const DynamicsProcessing::EngineArchitecture& engine)
+            REQUIRES(mMutex);
+    dp_fx::DPChannel* getChannel_l(int ch) REQUIRES(mMutex);
+    dp_fx::DPEq* getPreEq_l(int ch) REQUIRES(mMutex);
+    dp_fx::DPEq* getPostEq_l(int ch) REQUIRES(mMutex);
+    dp_fx::DPMbc* getMbc_l(int ch) REQUIRES(mMutex);
+    dp_fx::DPLimiter* getLimiter_l(int ch) REQUIRES(mMutex);
+    dp_fx::DPBandStage* getStageWithType_l(StageType type, int ch) REQUIRES(mMutex);
+    dp_fx::DPEq* getEqWithType_l(StageType type, int ch) REQUIRES(mMutex);
+    template <typename D>
+    RetCode setDpChannels_l(const std::vector<DynamicsProcessing::ChannelConfig>& channels,
+                            bool stageInUse, StageType type) REQUIRES(mMutex);
+    template <typename T /* BandConfig */>
+    RetCode setBands_l(const std::vector<T>& bands, int maxBand, StageType type) REQUIRES(mMutex);
+    RetCode setDpChannelBand_l(const std::any& anyConfig, StageType type, int maxCh, int maxBand,
+                               std::set<std::pair<int, int>>& chBandSet) REQUIRES(mMutex);
+
+    std::vector<DynamicsProcessing::EqBandConfig> getEqBandConfigs(StageType type);
+    std::vector<DynamicsProcessing::ChannelConfig> getChannelConfig(StageType type);
+
+    bool validateStageEnablement(const DynamicsProcessing::StageEnablement& enablement);
+    bool validateEngineConfig(const DynamicsProcessing::EngineArchitecture& engine);
+    bool validateEqBandConfig(const DynamicsProcessing::EqBandConfig& band, int maxChannel,
+                              int maxBand);
+    bool validateMbcBandConfig(const DynamicsProcessing::MbcBandConfig& band, int maxChannel,
+                               int maxBand);
+    bool validateLimiterConfig(const DynamicsProcessing::LimiterConfig& limiter, int maxChannel);
+    bool validateInputGainConfig(const DynamicsProcessing::InputGain& gain, int maxChannel);
+
+    inline bool validateCutoffFrequency(float freq);
+    inline bool validateChannel(int ch, int maxCh) { return ch >= 0 && ch < maxCh; }
+    inline bool validateBand(int band, int maxBand) { return band >= 0 && band < maxBand; }
+    inline bool validateTime(int time) { return time >= 0; }
+    inline bool validateRatio(int ratio) { return ratio >= 0; }
+    inline bool validateBandDb(int db) { return db <= 0; }
+};
+
+}  // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/media/libeffects/hapticgenerator/Android.bp b/media/libeffects/hapticgenerator/Android.bp
index 03ce329..fc80211 100644
--- a/media/libeffects/hapticgenerator/Android.bp
+++ b/media/libeffects/hapticgenerator/Android.bp
@@ -22,6 +22,24 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
+cc_defaults {
+    name : "hapticgeneratordefaults",
+    srcs: [
+        "Processors.cpp",
+    ],
+    shared_libs: [
+        "libaudioutils",
+        "libbase",
+        "liblog",
+        "libutils",
+        "libvibratorutils",
+    ],
+    header_libs: [
+        "libaudioeffects",
+    ],
+    relative_install_path: "soundfx",
+}
+
 cc_library_shared {
     name: "libhapticgenerator",
 
@@ -29,7 +47,10 @@
 
     srcs: [
         "EffectHapticGenerator.cpp",
-        "Processors.cpp",
+    ],
+
+    defaults: [
+        "hapticgeneratordefaults",
     ],
 
     cflags: [
@@ -42,19 +63,29 @@
                        // with/without `-ffast-math` for more context.
         "-fvisibility=hidden",
     ],
+}
 
-    shared_libs: [
-        "libaudioutils",
-        "libbase",
-        "libbinder",
-        "liblog",
-        "libutils",
-        "libvibrator",
+cc_library_shared {
+    name: "libhapticgeneratoraidl",
+
+    srcs: [
+        "aidl/EffectHapticGenerator.cpp",
+        "aidl/HapticGeneratorContext.cpp",
+        ":effectCommonFile",
     ],
 
-    relative_install_path: "soundfx",
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "hapticgeneratordefaults",
+    ],
 
-    header_libs: [
-        "libaudioeffects",
+    cflags: [
+        "-Wthread-safety",
+    ],
+
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
     ],
 }
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
new file mode 100644
index 0000000..031477f
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_HapticGeneratorImpl"
+
+#include <android-base/logging.h>
+#include <audio_effects/effect_hapticgenerator.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "EffectHapticGenerator.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidHapticGenerator;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator;
+using aidl::android::hardware::audio::effect::HapticGeneratorImpl;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidHapticGenerator()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<HapticGeneratorImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidHapticGenerator()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = HapticGeneratorImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string HapticGeneratorImpl::kEffectName = "Haptic Generator";
+const Descriptor HapticGeneratorImpl::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidHapticGenerator(),
+                          .uuid = getEffectImplUuidHapticGenerator(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+                   .name = HapticGeneratorImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus HapticGeneratorImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    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");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& hgParam = specific.get<Parameter::Specific::hapticGenerator>();
+    auto tag = hgParam.getTag();
+
+    switch (tag) {
+        case HapticGenerator::hapticScales: {
+            RETURN_IF(mContext->setHgHapticScales(hgParam.get<HapticGenerator::hapticScales>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setHapticScaleFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case HapticGenerator::vibratorInfo: {
+            RETURN_IF(mContext->setHgVibratorInformation(
+                              hgParam.get<HapticGenerator::vibratorInfo>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setVibratorInfoFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterSpecific(const Parameter::Id& id,
+                                                             Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto hgId = id.get<Parameter::Id::hapticGeneratorTag>();
+    auto hgIdTag = hgId.getTag();
+    switch (hgIdTag) {
+        case HapticGenerator::Id::commonTag:
+            return getParameterHapticGenerator(hgId.get<HapticGenerator::Id::commonTag>(),
+                                               specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(hgIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus HapticGeneratorImpl::getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+                                                                    Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    HapticGenerator hgParam;
+    switch (tag) {
+        case HapticGenerator::hapticScales: {
+            hgParam.set<HapticGenerator::hapticScales>(mContext->getHgHapticScales());
+            break;
+        }
+        case HapticGenerator::vibratorInfo: {
+            hgParam.set<HapticGenerator::vibratorInfo>(mContext->getHgVibratorInformation());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "HapticGeneratorTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::hapticGenerator>(hgParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> HapticGeneratorImpl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<HapticGeneratorContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode HapticGeneratorImpl::releaseContext() {
+    if (mContext) {
+        mContext->reset();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status HapticGeneratorImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
new file mode 100644
index 0000000..fe9616a
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/EffectHapticGenerator.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "HapticGeneratorContext.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class HapticGeneratorImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    HapticGeneratorImpl() { LOG(DEBUG) << __func__; }
+    ~HapticGeneratorImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<HapticGeneratorContext> mContext;
+    ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
+                                                   Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
new file mode 100644
index 0000000..de44e05
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.cpp
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_HapticGeneratorContext"
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <android-base/parsedouble.h>
+#include <android-base/properties.h>
+
+#include "HapticGeneratorContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+HapticGeneratorContext::HapticGeneratorContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+    mSampleRate = common.input.base.sampleRate;
+    mFrameCount = common.input.frameCount;
+    init_params(common.input.base.channelMask, common.output.base.channelMask);
+}
+
+HapticGeneratorContext::~HapticGeneratorContext() {
+    LOG(DEBUG) << __func__;
+    mState = HAPTIC_GENERATOR_STATE_UNINITIALIZED;
+}
+
+RetCode HapticGeneratorContext::enable() {
+    if (mState != HAPTIC_GENERATOR_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = HAPTIC_GENERATOR_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode HapticGeneratorContext::disable() {
+    if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void HapticGeneratorContext::reset() {
+    for (auto& filter : mProcessorsRecord.filters) {
+        filter->clear();
+    }
+    for (auto& slowEnv : mProcessorsRecord.slowEnvs) {
+        slowEnv->clear();
+    }
+    for (auto& distortion : mProcessorsRecord.distortions) {
+        distortion->clear();
+    }
+}
+
+RetCode HapticGeneratorContext::setHgHapticScales(
+        const std::vector<HapticGenerator::HapticScale>& hapticScales) {
+    std::lock_guard lg(mMutex);
+    for (auto hapticScale : hapticScales) {
+        mParams.mHapticScales.insert_or_assign(hapticScale.id, hapticScale.scale);
+    }
+    mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+    for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+        mParams.mMaxVibratorScale = std::max(mParams.mMaxVibratorScale, vibratorScale);
+    }
+    return RetCode::SUCCESS;
+}
+
+HapticGenerator::VibratorInformation HapticGeneratorContext::getHgVibratorInformation() {
+    std::lock_guard lg(mMutex);
+    return mParams.mVibratorInfo;
+}
+
+std::vector<HapticGenerator::HapticScale> HapticGeneratorContext::getHgHapticScales() {
+    std::vector<HapticGenerator::HapticScale> result;
+    std::lock_guard lg(mMutex);
+    for (const auto& [id, vibratorScale] : mParams.mHapticScales) {
+        result.push_back({id, vibratorScale});
+    }
+    return result;
+}
+
+RetCode HapticGeneratorContext::setHgVibratorInformation(
+        const HapticGenerator::VibratorInformation& vibratorInfo) {
+    {
+        std::lock_guard lg(mMutex);
+        mParams.mVibratorInfo = vibratorInfo;
+
+        if (mProcessorsRecord.bpf != nullptr) {
+            mProcessorsRecord.bpf->setCoefficients(
+                    ::android::audio_effect::haptic_generator::bpfCoefs(
+                            mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate));
+        }
+        if (mProcessorsRecord.bsf != nullptr) {
+            mProcessorsRecord.bsf->setCoefficients(
+                    ::android::audio_effect::haptic_generator::bsfCoefs(
+                            mParams.mVibratorInfo.resonantFrequencyHz,
+                            mParams.mVibratorInfo.qFactor, mParams.mVibratorInfo.qFactor / 2.0f,
+                            mSampleRate));
+        }
+    }
+    configure();
+    return RetCode::SUCCESS;
+}
+
+IEffect::Status HapticGeneratorContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+    auto frameSize = getInputFrameSize();
+    RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    // The audio data must not be modified but just written to
+    // output buffer according the access mode.
+    bool accumulate = false;
+    if (in != out) {
+        for (int i = 0; i < samples; i++) {
+            if (accumulate) {
+                out[i] += in[i];
+            } else {
+                out[i] = in[i];
+            }
+        }
+    }
+
+    if (mState != HAPTIC_GENERATOR_STATE_ACTIVE) {
+        return status;
+    }
+
+    std::lock_guard lg(mMutex);
+    if (mParams.mMaxVibratorScale == HapticGenerator::VibratorScale::MUTE) {
+        // Haptic channels are muted, not need to generate haptic data.
+        return {STATUS_OK, samples, samples};
+    }
+
+    // Resize buffer if the haptic sample count is greater than buffer size.
+    size_t hapticSampleCount = mFrameCount * mParams.mHapticChannelCount;
+    if (hapticSampleCount > mInputBuffer.size()) {
+        // The inputBuffer and outputBuffer must have the same size, which must be at least
+        // the haptic sample count.
+        mInputBuffer.resize(hapticSampleCount);
+        mOutputBuffer.resize(hapticSampleCount);
+    }
+
+    // Construct input buffer according to haptic channel source
+    for (size_t i = 0; i < mFrameCount; ++i) {
+        for (size_t j = 0; j < mParams.mHapticChannelCount; ++j) {
+            mInputBuffer[i * mParams.mHapticChannelCount + j] =
+                    in[i * mParams.mAudioChannelCount + mParams.mHapticChannelSource[j]];
+        }
+    }
+
+    float* hapticOutBuffer =
+            runProcessingChain(mInputBuffer.data(), mOutputBuffer.data(), mFrameCount);
+    ::android::os::scaleHapticData(
+            hapticOutBuffer, hapticSampleCount,
+            static_cast<::android::os::HapticScale>(mParams.mMaxVibratorScale),
+            mParams.mVibratorInfo.qFactor);
+
+    // For haptic data, the haptic playback thread will copy the data from effect input
+    // buffer, which contains haptic data at the end of the buffer, directly to sink buffer.
+    // In that case, copy haptic data to input buffer instead of output buffer.
+    // Note: this may not work with rpc/binder calls
+    int offset = samples;
+    for (int i = 0; i < hapticSampleCount; ++i) {
+        in[samples + i] = hapticOutBuffer[i];
+    }
+    return {STATUS_OK, samples, static_cast<int32_t>(samples + hapticSampleCount)};
+}
+
+void HapticGeneratorContext::init_params(media::audio::common::AudioChannelLayout inputChMask,
+                                         media::audio::common::AudioChannelLayout outputChMask) {
+    std::lock_guard lg(mMutex);
+    mParams.mMaxVibratorScale = HapticGenerator::VibratorScale::MUTE;
+    mParams.mVibratorInfo.resonantFrequencyHz = DEFAULT_RESONANT_FREQUENCY;
+    mParams.mVibratorInfo.qFactor = DEFAULT_BSF_ZERO_Q;
+
+    mParams.mAudioChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+            inputChMask, ~media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+    mParams.mHapticChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+            outputChMask, media::audio::common::AudioChannelLayout::LAYOUT_HAPTIC_AB);
+    LOG_ALWAYS_FATAL_IF(mParams.mHapticChannelCount > 2, "haptic channel count is too large");
+    for (size_t i = 0; i < mParams.mHapticChannelCount; ++i) {
+        // By default, use the first audio channel to generate haptic channels.
+        mParams.mHapticChannelSource[i] = 0;
+    }
+
+    mState = HAPTIC_GENERATOR_STATE_INITIALIZED;
+}
+
+float HapticGeneratorContext::getDistortionOutputGain() {
+    float distortionOutputGain = getFloatProperty(
+            "vendor.audio.hapticgenerator.distortion.output.gain", DEFAULT_DISTORTION_OUTPUT_GAIN);
+    LOG(DEBUG) << "Using distortion output gain as " << distortionOutputGain;
+    return distortionOutputGain;
+}
+
+float HapticGeneratorContext::getFloatProperty(const std::string& key, float defaultValue) {
+    float result;
+    std::string value = ::android::base::GetProperty(key, "");
+    if (!value.empty() && ::android::base::ParseFloat(value, &result)) {
+        return result;
+    }
+    return defaultValue;
+}
+
+void HapticGeneratorContext::addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter) {
+    // The process chain captures the shared pointer of the filter in lambda.
+    // The process record will keep a shared pointer to the filter so that it is possible to
+    // access the filter outside of the process chain.
+    mProcessorsRecord.filters.push_back(filter);
+    mProcessingChain.push_back([filter](float* out, const float* in, size_t frameCount) {
+        filter->process(out, in, frameCount);
+    });
+}
+
+/**
+ * Build haptic generator processing chain.
+ */
+void HapticGeneratorContext::buildProcessingChain() {
+    std::lock_guard lg(mMutex);
+    const size_t channelCount = mParams.mHapticChannelCount;
+    float highPassCornerFrequency = 50.0f;
+    auto hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+                                                                     mSampleRate, channelCount);
+    addBiquadFilter(hpf);
+    float lowPassCornerFrequency = 9000.0f;
+    auto lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency,
+                                                                     mSampleRate, channelCount);
+    addBiquadFilter(lpf);
+
+    auto ramp = std::make_shared<::android::audio_effect::haptic_generator::Ramp>(
+            channelCount);  // ramp = half-wave rectifier.
+    // The process chain captures the shared pointer of the ramp in lambda. It will be the only
+    // reference to the ramp.
+    // The process record will keep a weak pointer to the ramp so that it is possible to access
+    // the ramp outside of the process chain.
+    mProcessorsRecord.ramps.push_back(ramp);
+    mProcessingChain.push_back([ramp](float* out, const float* in, size_t frameCount) {
+        ramp->process(out, in, frameCount);
+    });
+
+    highPassCornerFrequency = 60.0f;
+    hpf = ::android::audio_effect::haptic_generator::createHPF2(highPassCornerFrequency,
+                                                                mSampleRate, channelCount);
+    addBiquadFilter(hpf);
+    lowPassCornerFrequency = 700.0f;
+    lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+                                                                channelCount);
+    addBiquadFilter(lpf);
+
+    lowPassCornerFrequency = 400.0f;
+    lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+                                                                channelCount);
+    addBiquadFilter(lpf);
+    lowPassCornerFrequency = 500.0f;
+    lpf = ::android::audio_effect::haptic_generator::createLPF2(lowPassCornerFrequency, mSampleRate,
+                                                                channelCount);
+    addBiquadFilter(lpf);
+
+    auto bpf = ::android::audio_effect::haptic_generator::createBPF(
+            mParams.mVibratorInfo.resonantFrequencyHz, DEFAULT_BPF_Q, mSampleRate, channelCount);
+    mProcessorsRecord.bpf = bpf;
+    addBiquadFilter(bpf);
+
+    float normalizationPower = DEFAULT_SLOW_ENV_NORMALIZATION_POWER;
+    // The process chain captures the shared pointer of the slow envelope in lambda. It will
+    // be the only reference to the slow envelope.
+    // The process record will keep a weak pointer to the slow envelope so that it is possible
+    // to access the slow envelope outside of the process chain.
+    // SlowEnvelope = partial normalizer, or AGC.
+    auto slowEnv = std::make_shared<::android::audio_effect::haptic_generator::SlowEnvelope>(
+            5.0f /*envCornerFrequency*/, mSampleRate, normalizationPower, 0.01f /*envOffset*/,
+            channelCount);
+    mProcessorsRecord.slowEnvs.push_back(slowEnv);
+    mProcessingChain.push_back([slowEnv](float* out, const float* in, size_t frameCount) {
+        slowEnv->process(out, in, frameCount);
+    });
+
+    auto bsf = ::android::audio_effect::haptic_generator::createBSF(
+            mParams.mVibratorInfo.resonantFrequencyHz, mParams.mVibratorInfo.qFactor,
+            mParams.mVibratorInfo.qFactor / 2.0f, mSampleRate, channelCount);
+    mProcessorsRecord.bsf = bsf;
+    addBiquadFilter(bsf);
+
+    // The process chain captures the shared pointer of the Distortion in lambda. It will
+    // be the only reference to the Distortion.
+    // The process record will keep a weak pointer to the Distortion so that it is possible
+    // to access the Distortion outside of the process chain.
+    auto distortion = std::make_shared<::android::audio_effect::haptic_generator::Distortion>(
+            DEFAULT_DISTORTION_CORNER_FREQUENCY, mSampleRate, DEFAULT_DISTORTION_INPUT_GAIN,
+            DEFAULT_DISTORTION_CUBE_THRESHOLD, getDistortionOutputGain(), channelCount);
+    mProcessorsRecord.distortions.push_back(distortion);
+    mProcessingChain.push_back([distortion](float* out, const float* in, size_t frameCount) {
+        distortion->process(out, in, frameCount);
+    });
+}
+
+void HapticGeneratorContext::configure() {
+    mProcessingChain.clear();
+    mProcessorsRecord.filters.clear();
+    mProcessorsRecord.ramps.clear();
+    mProcessorsRecord.slowEnvs.clear();
+    mProcessorsRecord.distortions.clear();
+
+    buildProcessingChain();
+}
+
+/**
+ * Run the processing chain to generate haptic data from audio data
+ *
+ * @param buf1 a buffer contains raw audio data
+ * @param buf2 a buffer that is large enough to keep all the data
+ * @param frameCount frame count of the data
+ *
+ * @return a pointer to the output buffer
+ */
+float* HapticGeneratorContext::runProcessingChain(float* buf1, float* buf2, size_t frameCount) {
+    float* in = buf1;
+    float* out = buf2;
+    for (const auto processingFunc : mProcessingChain) {
+        processingFunc(out, in, frameCount);
+        std::swap(in, out);
+    }
+    return in;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
new file mode 100644
index 0000000..a0a0a4c
--- /dev/null
+++ b/media/libeffects/hapticgenerator/aidl/HapticGeneratorContext.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <vibrator/ExternalVibrationUtils.h>
+#include <map>
+
+#include "Processors.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum HapticGeneratorState {
+    HAPTIC_GENERATOR_STATE_UNINITIALIZED,
+    HAPTIC_GENERATOR_STATE_INITIALIZED,
+    HAPTIC_GENERATOR_STATE_ACTIVE,
+};
+
+struct HapticGeneratorParam {
+    // The audio channels used to generate haptic channels. The first channel will be used to
+    // generate HAPTIC_A, The second channel will be used to generate HAPTIC_B.
+    // The value will be offset of audio channel
+    int mHapticChannelSource[2];
+
+    int mHapticChannelCount;
+    int mAudioChannelCount;
+
+    HapticGenerator::HapticScale mHapticScale;
+    std::map<int, HapticGenerator::VibratorScale> mHapticScales;
+    // max intensity will be used to scale haptic data.
+    HapticGenerator::VibratorScale mMaxVibratorScale;
+
+    HapticGenerator::VibratorInformation mVibratorInfo;
+};
+
+// A structure to keep all shared pointers for all processors in HapticGenerator.
+struct HapticGeneratorProcessorsRecord {
+    std::vector<std::shared_ptr<HapticBiquadFilter>> filters;
+    std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Ramp>> ramps;
+    std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::SlowEnvelope>> slowEnvs;
+    std::vector<std::shared_ptr<::android::audio_effect::haptic_generator::Distortion>> distortions;
+
+    // Cache band-pass filter and band-stop filter for updating parameters
+    // according to vibrator info
+    std::shared_ptr<HapticBiquadFilter> bpf;
+    std::shared_ptr<HapticBiquadFilter> bsf;
+};
+
+class HapticGeneratorContext final : public EffectContext {
+  public:
+    HapticGeneratorContext(int statusDepth, const Parameter::Common& common);
+    ~HapticGeneratorContext();
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
+    std::vector<HapticGenerator::HapticScale> getHgHapticScales();
+
+    RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo);
+    HapticGenerator::VibratorInformation getHgVibratorInformation();
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
+    static constexpr float DEFAULT_BSF_ZERO_Q = 8.0f;
+    static constexpr float DEFAULT_BSF_POLE_Q = 4.0f;
+    static constexpr float DEFAULT_DISTORTION_OUTPUT_GAIN = 1.5f;
+    static constexpr float DEFAULT_BPF_Q = 1.0f;
+    static constexpr float DEFAULT_SLOW_ENV_NORMALIZATION_POWER = -0.8f;
+    static constexpr float DEFAULT_DISTORTION_CORNER_FREQUENCY = 300.0f;
+    static constexpr float DEFAULT_DISTORTION_INPUT_GAIN = 0.3f;
+    static constexpr float DEFAULT_DISTORTION_CUBE_THRESHOLD = 0.1f;
+
+    std::mutex mMutex;
+    HapticGeneratorState mState;
+    HapticGeneratorParam mParams GUARDED_BY(mMutex);
+    int mSampleRate;
+    int mFrameCount = 0;
+
+    // A cache for all shared pointers of the HapticGenerator
+    struct HapticGeneratorProcessorsRecord mProcessorsRecord;
+
+    // Using a vector of functions to record the processing chain for haptic-generating algorithm.
+    // The three parameters of the processing functions are pointer to output buffer, pointer to
+    // input buffer and frame count.
+    std::vector<std::function<void(float*, const float*, size_t)>> mProcessingChain;
+
+    // inputBuffer is where to keep input buffer for the generating algorithm. It will be
+    // constructed according to hapticChannelSource.
+    std::vector<float> mInputBuffer;
+
+    // outputBuffer is a buffer having the same length as inputBuffer. It can be used as
+    // intermediate buffer in the generating algorithm.
+    std::vector<float> mOutputBuffer;
+
+    void init_params(media::audio::common::AudioChannelLayout inputChMask,
+                     media::audio::common::AudioChannelLayout outputChMask);
+    void configure();
+
+    float getDistortionOutputGain();
+    float getFloatProperty(const std::string& key, float defaultValue);
+    void addBiquadFilter(std::shared_ptr<HapticBiquadFilter> filter);
+    void buildProcessingChain();
+    float* runProcessingChain(float* buf1, float* buf2, size_t frameCount);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/Android.bp b/media/libeffects/loudness/Android.bp
index bcd6947..7acba11 100644
--- a/media/libeffects/loudness/Android.bp
+++ b/media/libeffects/loudness/Android.bp
@@ -44,3 +44,33 @@
 
     header_libs: ["libaudioeffects"],
 }
+
+cc_library_shared {
+    name: "libloudnessenhanceraidl",
+    srcs: [
+        "aidl/EffectLoudnessEnhancer.cpp",
+        "aidl/LoudnessEnhancerContext.cpp",
+        "dsp/core/dynamic_range_compression.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers",
+    ],
+    cflags: [
+        "-Wthread-safety",
+    ],
+    shared_libs: [
+        "libcutils",
+        "liblog",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
new file mode 100644
index 0000000..a7d9282
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_LoudnessEnhancerImpl"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "EffectLoudnessEnhancer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidLoudnessEnhancer;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::LoudnessEnhancerImpl;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidLoudnessEnhancer()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidLoudnessEnhancer()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = LoudnessEnhancerImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string LoudnessEnhancerImpl::kEffectName = "Loudness Enhancer";
+const Descriptor LoudnessEnhancerImpl::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidLoudnessEnhancer(),
+                          .uuid = getEffectImplUuidLoudnessEnhancer(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT, .insert = Flags::Insert::FIRST},
+                   .name = LoudnessEnhancerImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    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");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
+    auto tag = leParam.getTag();
+
+    switch (tag) {
+        case LoudnessEnhancer::gainMb: {
+            RETURN_IF(mContext->setLeGain(leParam.get<LoudnessEnhancer::gainMb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setGainMbFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterSpecific(const Parameter::Id& id,
+                                                              Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto leId = id.get<Parameter::Id::loudnessEnhancerTag>();
+    auto leIdTag = leId.getTag();
+    switch (leIdTag) {
+        case LoudnessEnhancer::Id::commonTag:
+            return getParameterLoudnessEnhancer(leId.get<LoudnessEnhancer::Id::commonTag>(),
+                                                specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(leIdTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerImpl::getParameterLoudnessEnhancer(
+        const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    LoudnessEnhancer leParam;
+    switch (tag) {
+        case LoudnessEnhancer::gainMb: {
+            leParam.set<LoudnessEnhancer::gainMb>(mContext->getLeGain());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::loudnessEnhancer>(leParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> LoudnessEnhancerImpl::createContext(
+        const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<LoudnessEnhancerContext>(1 /* statusFmqDepth */, common);
+    return mContext;
+}
+
+RetCode LoudnessEnhancerImpl::releaseContext() {
+    if (mContext) {
+        mContext->disable();
+        mContext->resetBuffer();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status LoudnessEnhancerImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
new file mode 100644
index 0000000..5b9e924
--- /dev/null
+++ b/media/libeffects/loudness/aidl/EffectLoudnessEnhancer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class LoudnessEnhancerImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Descriptor kDescriptor;
+    LoudnessEnhancerImpl() { LOG(DEBUG) << __func__; }
+    ~LoudnessEnhancerImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    std::shared_ptr<LoudnessEnhancerContext> mContext;
+    ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
+                                                    Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
new file mode 100644
index 0000000..bc3fa45
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "LoudnessEnhancerContext"
+
+#include <Utils.h>
+
+#include "LoudnessEnhancerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+LoudnessEnhancerContext::LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+    LOG(DEBUG) << __func__;
+    init_params();
+}
+
+LoudnessEnhancerContext::~LoudnessEnhancerContext() {
+    LOG(DEBUG) << __func__;
+}
+
+RetCode LoudnessEnhancerContext::enable() {
+    std::lock_guard lg(mMutex);
+    if (mState != LOUDNESS_ENHANCER_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = LOUDNESS_ENHANCER_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode LoudnessEnhancerContext::disable() {
+    std::lock_guard lg(mMutex);
+    if (mState != LOUDNESS_ENHANCER_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void LoudnessEnhancerContext::reset() {
+    float targetAmp = pow(10, mGain / 2000.0f);  // mB to linear amplification
+    std::lock_guard lg(mMutex);
+    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;
+}
+
+IEffect::Status LoudnessEnhancerContext::lvmProcess(float* in, float* out, int samples) {
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    RETURN_VALUE_IF(getInputFrameSize() != getOutputFrameSize(), status, "FrameSizeMismatch");
+    auto frameSize = getInputFrameSize();
+    RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+    std::lock_guard lg(mMutex);
+    status = {STATUS_INVALID_OPERATION, 0, 0};
+    RETURN_VALUE_IF(mState != LOUDNESS_ENHANCER_STATE_ACTIVE, status, "stateNotActive");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    // PcmType is always expected to be Float 32 bit.
+    constexpr float scale = 1 << 15;  // power of 2 is lossless conversion to int16_t range
+    constexpr float inverseScale = 1.f / scale;
+    const float inputAmp = pow(10, mGain / 2000.0f) * scale;
+    float leftSample, rightSample;
+
+    if (mCompressor != nullptr) {
+        for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+            // makeup gain is applied on the input of the compressor
+            leftSample = inputAmp * in[inIdx];
+            rightSample = inputAmp * in[inIdx + 1];
+            mCompressor->Compress(&leftSample, &rightSample);
+            in[inIdx] = leftSample * inverseScale;
+            in[inIdx + 1] = rightSample * inverseScale;
+        }
+    } else {
+        for (int inIdx = 0; inIdx < samples; inIdx += 2) {
+            leftSample = inputAmp * in[inIdx];
+            rightSample = inputAmp * in[inIdx + 1];
+            in[inIdx] = leftSample * inverseScale;
+            in[inIdx + 1] = rightSample * inverseScale;
+        }
+    }
+    bool accumulate = false;
+    if (in != out) {
+        for (int i = 0; i < samples; i++) {
+            if (accumulate) {
+                out[i] += in[i];
+            } else {
+                out[i] = in[i];
+            }
+        }
+    }
+    return {STATUS_OK, samples, samples};
+}
+
+void LoudnessEnhancerContext::init_params() {
+    int channelCount = ::aidl::android::hardware::audio::common::getChannelCount(
+            mCommon.input.base.channelMask);
+    LOG_ALWAYS_FATAL_IF(channelCount != 2, "channel count %d not supported", channelCount);
+
+    mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+    float targetAmp = pow(10, mGain / 2000.0f);  // mB to linear amplification
+    LOG(DEBUG) << __func__ << "Target gain = " << mGain << "mB <=> factor = " << targetAmp;
+
+    std::lock_guard lg(mMutex);
+    mCompressor = std::make_unique<le_fx::AdaptiveDynamicRangeCompression>();
+    mCompressor->Initialize(targetAmp, mCommon.input.base.sampleRate);
+    mState = LOUDNESS_ENHANCER_STATE_INITIALIZED;
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
new file mode 100644
index 0000000..9a1ec4c
--- /dev/null
+++ b/media/libeffects/loudness/aidl/LoudnessEnhancerContext.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <audio_effects/effect_loudnessenhancer.h>
+
+#include "dsp/core/dynamic_range_compression.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum LoudnessEnhancerState {
+    LOUDNESS_ENHANCER_STATE_UNINITIALIZED,
+    LOUDNESS_ENHANCER_STATE_INITIALIZED,
+    LOUDNESS_ENHANCER_STATE_ACTIVE,
+};
+
+class LoudnessEnhancerContext final : public EffectContext {
+  public:
+    LoudnessEnhancerContext(int statusDepth, const Parameter::Common& common);
+    ~LoudnessEnhancerContext();
+
+    RetCode enable();
+    RetCode disable();
+    void reset();
+
+    RetCode setLeGain(int gainMb);
+    int getLeGain() const { return mGain; }
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    std::mutex mMutex;
+    LoudnessEnhancerState mState GUARDED_BY(mMutex) = LOUDNESS_ENHANCER_STATE_UNINITIALIZED;
+    int mGain = LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB;
+    // In this implementation, there is no coupling between the compression on the left and right
+    // channels
+    std::unique_ptr<le_fx::AdaptiveDynamicRangeCompression> mCompressor GUARDED_BY(mMutex);
+
+    void init_params();
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/tests/Android.bp b/media/libeffects/lvm/tests/Android.bp
index 8870bb0..0568fbd 100644
--- a/media/libeffects/lvm/tests/Android.bp
+++ b/media/libeffects/lvm/tests/Android.bp
@@ -11,52 +11,33 @@
 
 cc_test {
     name: "EffectReverbTest",
-    vendor: true,
-    gtest: true,
-    host_supported: true,
-    // TODO(b/269868814)
-    test_options: {
-        unit_test: false,
-    },
+    defaults: [
+      "libeffects-test-defaults",
+    ],
     srcs: [
         "EffectReverbTest.cpp",
-        "EffectTestHelper.cpp",
     ],
     static_libs: [
-        "libaudioutils",
         "libreverb",
         "libreverbwrapper",
     ],
-    shared_libs: [
-        "liblog",
-    ],
     header_libs: [
         "libaudioeffects",
-        "libhardware_headers",
     ],
 }
 
 cc_test {
     name: "EffectBundleTest",
-    vendor: true,
-    gtest: true,
-    host_supported: true,
-    test_suites: ["device-tests"],
+    defaults: [
+      "libeffects-test-defaults",
+    ],
     srcs: [
         "EffectBundleTest.cpp",
-        "EffectTestHelper.cpp",
     ],
     static_libs: [
-        "libaudioutils",
         "libbundlewrapper",
         "libmusicbundle",
     ],
-    shared_libs: [
-        "liblog",
-    ],
-    header_libs: [
-        "libhardware_headers",
-    ],
 }
 
 cc_test {
diff --git a/media/libeffects/lvm/tests/EffectReverbTest.cpp b/media/libeffects/lvm/tests/EffectReverbTest.cpp
index 59453eb..aaac782 100644
--- a/media/libeffects/lvm/tests/EffectReverbTest.cpp
+++ b/media/libeffects/lvm/tests/EffectReverbTest.cpp
@@ -33,6 +33,27 @@
 
 constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
 
+static constexpr audio_channel_mask_t kChMasks[] = {
+        AUDIO_CHANNEL_OUT_MONO,          AUDIO_CHANNEL_OUT_STEREO,
+        AUDIO_CHANNEL_OUT_2POINT1,       AUDIO_CHANNEL_OUT_5POINT1,
+        AUDIO_CHANNEL_OUT_7POINT1POINT4, AUDIO_CHANNEL_INDEX_MASK_23,
+        AUDIO_CHANNEL_OUT_22POINT2,
+};
+
+static constexpr size_t kNumChMasks = std::size(kChMasks);
+
+static constexpr size_t kSampleRates[] = {8000, 11025, 44100, 48000, 192000};
+
+static constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+static constexpr size_t kFrameCounts[] = {4, 512};
+
+static constexpr size_t kNumFrameCounts = std::size(kFrameCounts);
+
+static constexpr size_t kLoopCounts[] = {1, 4};
+
+static constexpr size_t kNumLoopCounts = std::size(kLoopCounts);
+
 static bool isAuxMode(const effect_uuid_t* uuid) {
     // Update this, if the order of effects in kEffectUuids is updated
     return (uuid == &kEffectUuids[2] || uuid == &kEffectUuids[3]);
@@ -50,15 +71,15 @@
 class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
   public:
     SingleEffectTest()
-        : mSampleRate(EffectTestHelper::kSampleRates[std::get<1>(GetParam())]),
-          mFrameCount(EffectTestHelper::kFrameCounts[std::get<2>(GetParam())]),
-          mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+        : mSampleRate(kSampleRates[std::get<1>(GetParam())]),
+          mFrameCount(kFrameCounts[std::get<2>(GetParam())]),
+          mLoopCount(kLoopCounts[std::get<3>(GetParam())]),
           mTotalFrameCount(mFrameCount * mLoopCount),
           mUuid(&kEffectUuids[std::get<4>(GetParam())]),
           mInChMask(isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO
-                                     : EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+                                     : kChMasks[std::get<0>(GetParam())]),
           mInChannelCount(audio_channel_count_from_out_mask(mInChMask)),
-          mOutChMask(EffectTestHelper::kChMasks[std::get<0>(GetParam())]),
+          mOutChMask(kChMasks[std::get<0>(GetParam())]),
           mOutChannelCount(audio_channel_count_from_out_mask(mOutChMask)),
           mPreset(kPresets[std::get<5>(GetParam())]) {}
 
@@ -100,10 +121,10 @@
 
 INSTANTIATE_TEST_SUITE_P(
         EffectReverbTestAll, SingleEffectTest,
-        ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumChMasks),
-                           ::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
-                           ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
-                           ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+        ::testing::Combine(::testing::Range(0, (int)kNumChMasks),
+                           ::testing::Range(0, (int)kNumSampleRates),
+                           ::testing::Range(0, (int)kNumFrameCounts),
+                           ::testing::Range(0, (int)kNumLoopCounts),
                            ::testing::Range(0, (int)kNumEffectUuids),
                            ::testing::Range(0, (int)kNumPresets)));
 
@@ -112,9 +133,9 @@
     : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
   public:
     SingleEffectComparisonTest()
-        : mSampleRate(EffectTestHelper::kSampleRates[std::get<0>(GetParam())]),
-          mFrameCount(EffectTestHelper::kFrameCounts[std::get<1>(GetParam())]),
-          mLoopCount(EffectTestHelper::kLoopCounts[std::get<2>(GetParam())]),
+        : mSampleRate(kSampleRates[std::get<0>(GetParam())]),
+          mFrameCount(kFrameCounts[std::get<1>(GetParam())]),
+          mLoopCount(kLoopCounts[std::get<2>(GetParam())]),
           mTotalFrameCount(mFrameCount * mLoopCount),
           mUuid(&kEffectUuids[std::get<3>(GetParam())]),
           mPreset(kPresets[std::get<4>(GetParam())]) {}
@@ -173,7 +194,7 @@
     std::vector<int16_t> monoRefI16(mTotalFrameCount);
     memcpy_to_i16_from_float(monoRefI16.data(), monoOutput.data(), mTotalFrameCount);
 
-    for (size_t outChMask : EffectTestHelper::kChMasks) {
+    for (size_t outChMask : kChMasks) {
         size_t outChannelCount = audio_channel_count_from_out_mask(outChMask);
         size_t inChMask = isAuxMode(mUuid) ? AUDIO_CHANNEL_OUT_MONO : outChMask;
 
@@ -225,9 +246,9 @@
 
 INSTANTIATE_TEST_SUITE_P(
         EffectReverbTestAll, SingleEffectComparisonTest,
-        ::testing::Combine(::testing::Range(0, (int)EffectTestHelper::kNumSampleRates),
-                           ::testing::Range(0, (int)EffectTestHelper::kNumFrameCounts),
-                           ::testing::Range(0, (int)EffectTestHelper::kNumLoopCounts),
+        ::testing::Combine(::testing::Range(0, (int)kNumSampleRates),
+                           ::testing::Range(0, (int)kNumFrameCounts),
+                           ::testing::Range(0, (int)kNumLoopCounts),
                            ::testing::Range(0, (int)kNumEffectUuids),
                            ::testing::Range(0, (int)kNumPresets)));
 
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
new file mode 100644
index 0000000..d026e2b
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.cpp
@@ -0,0 +1,851 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+
+#define LOG_TAG "BundleContext"
+#include <android-base/logging.h>
+#include <Utils.h>
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+#include "math.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using ::aidl::android::media::audio::common::AudioChannelLayout;
+using ::aidl::android::media::audio::common::AudioDeviceDescription;
+using ::aidl::android::media::audio::common::AudioDeviceType;
+
+RetCode BundleContext::init() {
+    std::lock_guard lg(mMutex);
+    // init with pre-defined preset NORMAL
+    for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+        mBandGaindB[i] = lvm::kSoftPresets[0 /* normal */][i];
+    }
+
+    // allocate lvm instance
+    LVM_ReturnStatus_en status;
+    LVM_InstParams_t params = {.BufferMode = LVM_UNMANAGED_BUFFERS,
+                               .MaxBlockSize = lvm::MAX_CALL_SIZE,
+                               .EQNB_NumBands = lvm::MAX_NUM_BANDS,
+                               .PSA_Included = LVM_PSA_ON};
+    status = LVM_GetInstanceHandle(&mInstance, &params);
+    GOTO_IF_LVM_ERROR(status, deinit, "LVM_GetInstanceHandleFailed");
+
+    // set control
+    LVM_ControlParams_t controlParams;
+    initControlParameter(controlParams);
+    status = LVM_SetControlParameters(mInstance, &controlParams);
+    GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetControlParametersFailed");
+
+    /* Set the headroom parameters */
+    LVM_HeadroomParams_t headroomParams;
+    initHeadroomParameter(headroomParams);
+    status = LVM_SetHeadroomParams(mInstance, &headroomParams);
+    GOTO_IF_LVM_ERROR(status, deinit, "LVM_SetHeadroomParamsFailed");
+
+    return RetCode::SUCCESS;
+
+deinit:
+    deInit();
+    return RetCode::ERROR_EFFECT_LIB_ERROR;
+}
+
+void BundleContext::deInit() {
+    std::lock_guard lg(mMutex);
+    if (mInstance) {
+        LVM_DelInstanceHandle(&mInstance);
+        mInstance = nullptr;
+    }
+}
+
+RetCode BundleContext::enable() {
+    if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+    // Bass boost or Virtualizer can be temporarily disabled if playing over device speaker due to
+    // their nature.
+    bool tempDisabled = false;
+    switch (mType) {
+        case lvm::BundleEffectType::EQUALIZER:
+            LOG(DEBUG) << __func__ << " enable bundle EQ";
+            if (mSamplesToExitCountEq <= 0) mNumberEffectsEnabled++;
+            mSamplesToExitCountEq = (mSamplesPerSecond * 0.1);
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+            break;
+        case lvm::BundleEffectType::BASS_BOOST:
+            LOG(DEBUG) << __func__ << " enable bundle BB";
+            if (mSamplesToExitCountBb <= 0) mNumberEffectsEnabled++;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+            mSamplesToExitCountBb = (mSamplesPerSecond * 0.1);
+            tempDisabled = mBassTempDisabled;
+            break;
+        case lvm::BundleEffectType::VIRTUALIZER:
+            LOG(DEBUG) << __func__ << " enable bundle VR";
+            if (mSamplesToExitCountVirt <= 0) mNumberEffectsEnabled++;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+            mSamplesToExitCountVirt = (mSamplesPerSecond * 0.1);
+            tempDisabled = mVirtualizerTempDisabled;
+            break;
+        case lvm::BundleEffectType::VOLUME:
+            LOG(DEBUG) << __func__ << " enable bundle VOL";
+            if ((mEffectInDrain & (1 << int(lvm::BundleEffectType::VOLUME))) == 0)
+                mNumberEffectsEnabled++;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+            break;
+    }
+    mEnabled = true;
+    return (tempDisabled ? RetCode::SUCCESS : enableOperatingMode());
+}
+
+RetCode BundleContext::enableOperatingMode() {
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
+        switch (mType) {
+            case lvm::BundleEffectType::EQUALIZER:
+                LOG(DEBUG) << __func__ << " enable bundle EQ";
+                params.EQNB_OperatingMode = LVM_EQNB_ON;
+                break;
+            case lvm::BundleEffectType::BASS_BOOST:
+                LOG(DEBUG) << __func__ << " enable bundle BB";
+                params.BE_OperatingMode = LVM_BE_ON;
+                break;
+            case lvm::BundleEffectType::VIRTUALIZER:
+                LOG(DEBUG) << __func__ << " enable bundle VR";
+                params.VirtualizerOperatingMode = LVM_MODE_ON;
+                break;
+            case lvm::BundleEffectType::VOLUME:
+                LOG(DEBUG) << __func__ << " enable bundle VOL";
+                break;
+        }
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
+    }
+    return limitLevel();
+}
+
+RetCode BundleContext::disable() {
+    if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+    switch (mType) {
+        case lvm::BundleEffectType::EQUALIZER:
+            LOG(DEBUG) << __func__ << " disable bundle EQ";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::EQUALIZER);
+            break;
+        case lvm::BundleEffectType::BASS_BOOST:
+            LOG(DEBUG) << __func__ << " disable bundle BB";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::BASS_BOOST);
+            break;
+        case lvm::BundleEffectType::VIRTUALIZER:
+            LOG(DEBUG) << __func__ << " disable bundle VR";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::VIRTUALIZER);
+            break;
+        case lvm::BundleEffectType::VOLUME:
+            LOG(DEBUG) << __func__ << " disable bundle VOL";
+            mEffectInDrain |= 1 << int(lvm::BundleEffectType::VOLUME);
+            break;
+    }
+    mEnabled = false;
+    return disableOperatingMode();
+}
+
+RetCode BundleContext::disableOperatingMode() {
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, "failGetControlParams");
+        switch (mType) {
+            case lvm::BundleEffectType::EQUALIZER:
+                LOG(DEBUG) << __func__ << " disable bundle EQ";
+                params.EQNB_OperatingMode = LVM_EQNB_OFF;
+                break;
+            case lvm::BundleEffectType::BASS_BOOST:
+                LOG(DEBUG) << __func__ << " disable bundle BB";
+                params.BE_OperatingMode = LVM_BE_OFF;
+                break;
+            case lvm::BundleEffectType::VIRTUALIZER:
+                LOG(DEBUG) << __func__ << " disable bundle VR";
+                params.VirtualizerOperatingMode = LVM_MODE_OFF;
+                break;
+            case lvm::BundleEffectType::VOLUME:
+                LOG(DEBUG) << __func__ << " disable bundle VOL";
+                break;
+        }
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, "failSetControlParams");
+    }
+    mEnabled = false;
+    return limitLevel();
+}
+
+RetCode BundleContext::limitLevel() {
+    int gainCorrection = 0;
+    // Count the energy contribution per band for EQ and BassBoost only if they are active.
+    float energyContribution = 0;
+    float energyCross = 0;
+    float energyBassBoost = 0;
+    float crossCorrection = 0;
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        bool eqEnabled = params.EQNB_OperatingMode == LVM_EQNB_ON;
+        bool bbEnabled = params.BE_OperatingMode == LVM_BE_ON;
+        bool viEnabled = params.VirtualizerOperatingMode == LVM_MODE_ON;
+
+        if (eqEnabled) {
+            for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+                float bandFactor = mBandGaindB[i] / 15.0;
+                float bandCoefficient = lvm::kBandEnergyCoefficient[i];
+                float bandEnergy = bandFactor * bandCoefficient * bandCoefficient;
+                if (bandEnergy > 0) energyContribution += bandEnergy;
+            }
+
+            // cross EQ coefficients
+            float bandFactorSum = 0;
+            for (int i = 0; i < lvm::MAX_NUM_BANDS - 1; i++) {
+                float bandFactor1 = mBandGaindB[i] / 15.0;
+                float bandFactor2 = mBandGaindB[i + 1] / 15.0;
+
+                if (bandFactor1 > 0 && bandFactor2 > 0) {
+                    float crossEnergy =
+                            bandFactor1 * bandFactor2 * lvm::kBandEnergyCrossCoefficient[i];
+                    bandFactorSum += bandFactor1 * bandFactor2;
+
+                    if (crossEnergy > 0) energyCross += crossEnergy;
+                }
+            }
+            bandFactorSum -= 1.0;
+            if (bandFactorSum > 0) crossCorrection = bandFactorSum * 0.7;
+        }
+        // BassBoost contribution
+        if (bbEnabled) {
+            float boostFactor = mBassStrengthSaved / 1000.0;
+            float boostCoefficient = lvm::kBassBoostEnergyCoefficient;
+
+            energyContribution += boostFactor * boostCoefficient * boostCoefficient;
+
+            if (eqEnabled) {
+                for (int i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+                    float bandFactor = mBandGaindB[i] / 15.0;
+                    float bandCrossCoefficient = lvm::kBassBoostEnergyCrossCoefficient[i];
+                    float bandEnergy = boostFactor * bandFactor * bandCrossCoefficient;
+                    if (bandEnergy > 0) energyBassBoost += bandEnergy;
+                }
+            }
+        }
+        // Virtualizer contribution
+        if (viEnabled) {
+            energyContribution += lvm::kVirtualizerContribution * lvm::kVirtualizerContribution;
+        }
+
+        double totalEnergyEstimation =
+                sqrt(energyContribution + energyCross + energyBassBoost) - crossCorrection;
+        LOG(INFO) << " TOTAL energy estimation: " << totalEnergyEstimation << " dB";
+
+        // roundoff
+        int maxLevelRound = (int)(totalEnergyEstimation + 0.99);
+        if (maxLevelRound + mVolume > 0) {
+            gainCorrection = maxLevelRound + mVolume;
+        }
+
+        params.VC_EffectLevel = mVolume - gainCorrection;
+        if (params.VC_EffectLevel < -96) {
+            params.VC_EffectLevel = -96;
+        }
+        LOG(INFO) << "\tVol: " << mVolume << ", GainCorrection: " << gainCorrection
+                  << ", Actual vol: " << params.VC_EffectLevel;
+
+        /* Activate the initial settings */
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+
+        if (mFirstVolume) {
+            RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetVolumeNoSmoothing(mInstance, &params),
+                            RetCode::ERROR_EFFECT_LIB_ERROR, " setVolumeNoSmoothingFailed");
+            LOG(INFO) << "\tLVM_VOLUME: Disabling Smoothing for first volume change to remove "
+                         "spikes/clicks";
+            mFirstVolume = false;
+        }
+    }
+
+    return RetCode::SUCCESS;
+}
+
+bool BundleContext::isDeviceSupportedBassBoost(
+        const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
+    for (const auto& device : devices) {
+        if (device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER, ""} &&
+            device != AudioDeviceDescription{AudioDeviceType::OUT_CARKIT,
+                                             AudioDeviceDescription::CONNECTION_BT_SCO} &&
+            device != AudioDeviceDescription{AudioDeviceType::OUT_SPEAKER,
+                                             AudioDeviceDescription::CONNECTION_BT_A2DP}) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool BundleContext::isDeviceSupportedVirtualizer(
+        const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
+    for (const auto& device : devices) {
+        if (device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+                                             AudioDeviceDescription::CONNECTION_ANALOG} &&
+            device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+                                             AudioDeviceDescription::CONNECTION_ANALOG} &&
+            device != AudioDeviceDescription{AudioDeviceType::OUT_HEADPHONE,
+                                             AudioDeviceDescription::CONNECTION_BT_A2DP} &&
+            device != AudioDeviceDescription{AudioDeviceType::OUT_HEADSET,
+                                             AudioDeviceDescription::CONNECTION_USB}) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool BundleContext::isConfigSupportedVirtualizer(size_t channelCount,
+                                                 const AudioDeviceDescription& device) {
+    return (channelCount >= 1 && channelCount <= FCC_2) && isDeviceSupportedVirtualizer({device});
+}
+
+RetCode BundleContext::setOutputDevice(
+        const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices) {
+    mOutputDevice = devices;
+    switch (mType) {
+        case lvm::BundleEffectType::BASS_BOOST:
+            if (!isDeviceSupportedBassBoost(devices)) {
+                // If a device doesn't support bass boost, the effect must be temporarily disabled.
+                // The effect must still report its original state as this can only be changed by
+                // the start/stop commands.
+                if (mEnabled) {
+                    disableOperatingMode();
+                }
+                mBassTempDisabled = true;
+            } else {
+                // If a device supports bass boost and the effect has been temporarily disabled
+                // previously then re-enable it
+                if (!mEnabled) {
+                    enableOperatingMode();
+                }
+                mBassTempDisabled = false;
+            }
+            break;
+        case lvm::BundleEffectType::VIRTUALIZER:
+            if (!isDeviceSupportedVirtualizer(devices)) {
+                if (mEnabled) {
+                    disableOperatingMode();
+                }
+                mVirtualizerTempDisabled = true;
+            } else {
+                if (!mEnabled) {
+                    enableOperatingMode();
+                }
+                mVirtualizerTempDisabled = false;
+            }
+            break;
+        default:
+            break;
+    }
+    return RetCode::SUCCESS;
+}
+
+LVM_INT16 BundleContext::LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const {
+    LVM_INT16 db_fix;
+    LVM_INT16 Shift;
+    LVM_INT16 SmallRemainder;
+    LVM_UINT32 Remainder = (LVM_UINT32)Lin_fix;
+
+    /* Count leading bits, 1 cycle in assembly*/
+    for (Shift = 0; Shift < 32; Shift++) {
+        if ((Remainder & 0x80000000U) != 0) {
+            break;
+        }
+        Remainder = Remainder << 1;
+    }
+
+    /*
+     * Based on the approximation equation (for Q11.4 format):
+     *
+     * dB = -96 * Shift + 16 * (8 * Remainder - 2 * Remainder^2)
+     */
+    db_fix = (LVM_INT16)(-96 * Shift); /* Six dB steps in Q11.4 format*/
+    SmallRemainder = (LVM_INT16)((Remainder & 0x7fffffff) >> 24);
+    db_fix = (LVM_INT16)(db_fix + SmallRemainder);
+    SmallRemainder = (LVM_INT16)(SmallRemainder * SmallRemainder);
+    db_fix = (LVM_INT16)(db_fix - (LVM_INT16)((LVM_UINT16)SmallRemainder >> 9));
+
+    /* Correct for small offset */
+    db_fix = (LVM_INT16)(db_fix - 5);
+
+    return db_fix;
+}
+
+// TODO: replace with more generic approach, like: audio_utils_power_from_amplitude
+int16_t BundleContext::VolToDb(uint32_t vol) const {
+    int16_t dB;
+
+    dB = LVC_ToDB_s32Tos16(vol << 7);
+    dB = (dB + 8) >> 4;
+    dB = (dB < -96) ? -96 : dB;
+
+    return dB;
+}
+
+RetCode BundleContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
+    LVM_ControlParams_t params;
+    LVM_ReturnStatus_en status = LVM_SUCCESS;
+
+    // Convert volume to dB
+    int leftdB = VolToDb(volume.left);
+    int rightdB = VolToDb(volume.right);
+    int maxdB = std::max(leftdB, rightdB);
+    int pandB = rightdB - leftdB;
+    setVolumeLevel(maxdB * 100);
+    LOG(DEBUG) << __func__ << " pandB: " << pandB << " maxdB " << maxdB;
+
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, "");
+        params.VC_Balance = pandB;
+
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, "");
+    }
+    mVolumeStereo = volume;
+    return RetCode::SUCCESS;
+}
+
+RetCode BundleContext::setEqualizerPreset(const std::size_t presetIdx) {
+    if (presetIdx < 0 || presetIdx >= lvm::MAX_NUM_PRESETS) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+
+    std::vector<Equalizer::BandLevel> bandLevels;
+    bandLevels.reserve(lvm::MAX_NUM_BANDS);
+    for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+        bandLevels.emplace_back(
+                Equalizer::BandLevel{static_cast<int32_t>(i), lvm::kSoftPresets[presetIdx][i]});
+    }
+
+    RetCode ret = updateControlParameter(bandLevels);
+    if (RetCode::SUCCESS == ret) {
+        mCurPresetIdx = presetIdx;
+        LOG(INFO) << __func__ << " success with " << presetIdx;
+    } else {
+        LOG(ERROR) << __func__ << " failed to setPreset " << presetIdx;
+    }
+    return ret;
+}
+
+RetCode BundleContext::setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
+    RETURN_VALUE_IF(bandLevels.size() > lvm::MAX_NUM_BANDS || bandLevels.empty(),
+                    RetCode::ERROR_ILLEGAL_PARAMETER, "sizeExceedMax");
+    RetCode ret = updateControlParameter(bandLevels);
+    if (RetCode::SUCCESS == ret) {
+        mCurPresetIdx = lvm::PRESET_CUSTOM;
+        LOG(INFO) << __func__ << " succeed with " << ::android::internal::ToString(bandLevels);
+    } else {
+        LOG(ERROR) << __func__ << " failed with " << ::android::internal::ToString(bandLevels);
+    }
+    return ret;
+}
+
+std::vector<Equalizer::BandLevel> BundleContext::getEqualizerBandLevels() const {
+    std::vector<Equalizer::BandLevel> bandLevels;
+    bandLevels.reserve(lvm::MAX_NUM_BANDS);
+    for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+        bandLevels.emplace_back(Equalizer::BandLevel{static_cast<int32_t>(i), mBandGaindB[i]});
+    }
+    return bandLevels;
+}
+
+std::vector<int32_t> BundleContext::getEqualizerCenterFreqs() {
+    std::vector<int32_t> freqs;
+
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        /* Get the current settings */
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params), freqs,
+                        " getControlParamFailed");
+        for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+            freqs.push_back((int32_t)params.pEQNB_BandDefinition[i].Frequency * 1000);
+        }
+    }
+
+    return freqs;
+}
+
+bool BundleContext::isBandLevelIndexInRange(
+        const std::vector<Equalizer::BandLevel>& bandLevels) const {
+    const auto [min, max] =
+            std::minmax_element(bandLevels.begin(), bandLevels.end(),
+                                [](const auto& a, const auto& b) { return a.index < b.index; });
+    return min->index >= 0 && max->index < lvm::MAX_NUM_BANDS;
+}
+
+RetCode BundleContext::updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels) {
+    RETURN_VALUE_IF(!isBandLevelIndexInRange(bandLevels), RetCode::ERROR_ILLEGAL_PARAMETER,
+                    "indexOutOfRange");
+
+    std::array<int, lvm::MAX_NUM_BANDS> tempLevel;
+    for (const auto& it : bandLevels) {
+        tempLevel[it.index] = it.levelMb;
+    }
+
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+            params.pEQNB_BandDefinition[i].Frequency = lvm::kPresetsFrequencies[i];
+            params.pEQNB_BandDefinition[i].QFactor = lvm::kPresetsQFactors[i];
+            params.pEQNB_BandDefinition[i].Gain = tempLevel[i];
+        }
+
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mBandGaindB = tempLevel;
+    LOG(INFO) << __func__ << " update bandGain to " << ::android::internal::ToString(mBandGaindB);
+
+    return RetCode::SUCCESS;
+}
+
+RetCode BundleContext::setBassBoostStrength(int strength) {
+    // Update Control Parameter
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.BE_EffectLevel = (LVM_INT16)((15 * strength) / 1000);
+        params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mBassStrengthSaved = strength;
+    LOG(INFO) << __func__ << " success with strength " << strength;
+    return limitLevel();
+}
+
+RetCode BundleContext::setVolumeLevel(int level) {
+    if (mMuteEnabled) {
+        mLevelSaved = level / 100;
+    } else {
+        mVolume = level / 100;
+    }
+    LOG(INFO) << __func__ << " success with level " << level;
+    return limitLevel();
+}
+
+int BundleContext::getVolumeLevel() const {
+    return (mMuteEnabled ? mLevelSaved * 100 : mVolume * 100);
+}
+
+RetCode BundleContext::setVolumeMute(bool mute) {
+    mMuteEnabled = mute;
+    if (mMuteEnabled) {
+        mLevelSaved = mVolume;
+        mVolume = -96;
+    } else {
+        mVolume = mLevelSaved;
+    }
+    return limitLevel();
+}
+
+RetCode BundleContext::setVirtualizerStrength(int strength) {
+    // Update Control Parameter
+    LVM_ControlParams_t params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.CS_EffectLevel = ((strength * 32767) / 1000);
+
+        RETURN_VALUE_IF(LVM_SUCCESS != LVM_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+
+    mVirtStrengthSaved = strength;
+    LOG(INFO) << __func__ << " success with strength " << strength;
+    return limitLevel();
+}
+
+
+RetCode BundleContext::setForcedDevice(
+        const ::aidl::android::media::audio::common::AudioDeviceDescription& device) {
+    RETURN_VALUE_IF(true != isDeviceSupportedVirtualizer({device}), RetCode::ERROR_EFFECT_LIB_ERROR,
+                    " deviceNotSupportVirtualizer");
+    mForceDevice = device;
+    return RetCode::SUCCESS;
+}
+
+void BundleContext::initControlParameter(LVM_ControlParams_t& params) const {
+    /* General parameters */
+    params.OperatingMode = LVM_MODE_ON;
+    params.SampleRate = LVM_FS_44100;
+    params.SourceFormat = LVM_STEREO;
+    params.SpeakerType = LVM_HEADPHONES;
+
+    /* Concert Sound parameters */
+    params.VirtualizerOperatingMode = LVM_MODE_OFF;
+    params.VirtualizerType = LVM_CONCERTSOUND;
+    params.VirtualizerReverbLevel = 100;
+    params.CS_EffectLevel = LVM_CS_EFFECT_NONE;
+
+    params.EQNB_OperatingMode = LVM_EQNB_OFF;
+    params.EQNB_NBands = lvm::MAX_NUM_BANDS;
+    params.pEQNB_BandDefinition = getDefaultEqualizerBandDefs();
+
+    /* Volume Control parameters */
+    params.VC_EffectLevel = 0;
+    params.VC_Balance = 0;
+
+    /* Treble Enhancement parameters */
+    params.TE_OperatingMode = LVM_TE_OFF;
+    params.TE_EffectLevel = 0;
+
+    /* PSA Control parameters */
+    params.PSA_Enable = LVM_PSA_OFF;
+    params.PSA_PeakDecayRate = (LVM_PSA_DecaySpeed_en)0;
+
+    /* Bass Enhancement parameters */
+    params.BE_OperatingMode = LVM_BE_OFF;
+    params.BE_EffectLevel = 0;
+    params.BE_CentreFreq = LVM_BE_CENTRE_90Hz;
+    params.BE_HPF = LVM_BE_HPF_ON;
+
+    /* PSA Control parameters */
+    params.PSA_Enable = LVM_PSA_OFF;
+    params.PSA_PeakDecayRate = LVM_PSA_SPEED_MEDIUM;
+
+    /* TE Control parameters */
+    params.TE_OperatingMode = LVM_TE_OFF;
+    params.TE_EffectLevel = 0;
+
+    params.NrChannels = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
+    params.ChMask = AUDIO_CHANNEL_OUT_STEREO;
+    params.SourceFormat = LVM_STEREO;
+}
+
+void BundleContext::initHeadroomParameter(LVM_HeadroomParams_t& params) const {
+    params.pHeadroomDefinition = getDefaultEqualizerHeadroomBanDefs();
+    params.NHeadroomBands = 2;
+    params.Headroom_OperatingMode = LVM_HEADROOM_OFF;
+}
+
+LVM_EQNB_BandDef_t *BundleContext::getDefaultEqualizerBandDefs() {
+    static LVM_EQNB_BandDef_t* BandDefs = []() {
+        static LVM_EQNB_BandDef_t tempDefs[lvm::MAX_NUM_BANDS];
+        /* N-Band Equaliser parameters */
+        for (std::size_t i = 0; i < lvm::MAX_NUM_BANDS; i++) {
+            tempDefs[i].Frequency = lvm::kPresetsFrequencies[i];
+            tempDefs[i].QFactor = lvm::kPresetsQFactors[i];
+            tempDefs[i].Gain = lvm::kSoftPresets[0/* normal */][i];
+        }
+        return tempDefs;
+    }();
+
+    return BandDefs;
+}
+
+LVM_HeadroomBandDef_t *BundleContext::getDefaultEqualizerHeadroomBanDefs() {
+    static LVM_HeadroomBandDef_t HeadroomBandDef[LVM_HEADROOM_MAX_NBANDS] = {
+            {
+                    .Limit_Low = 20,
+                    .Limit_High = 4999,
+                    .Headroom_Offset = 0,
+            },
+            {
+                    .Limit_Low = 5000,
+                    .Limit_High = 24000,
+                    .Headroom_Offset = 0,
+            },
+    };
+    return HeadroomBandDef;
+}
+
+std::vector<Virtualizer::ChannelAngle> BundleContext::getSpeakerAngles(
+        const Virtualizer::SpeakerAnglesPayload payload) {
+    std::vector<Virtualizer::ChannelAngle> angles;
+    auto chCount = ::aidl::android::hardware::audio::common::getChannelCount(payload.layout);
+    RETURN_VALUE_IF(!isConfigSupportedVirtualizer(chCount, payload.device), angles,
+                    "payloadNotSupported");
+
+    if (chCount == 1) {
+        angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
+                   .azimuthDegree = 0,
+                   .elevationDegree = 0}};
+    } else {
+        angles = {{.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_LEFT,
+                   .azimuthDegree = -90,
+                   .elevationDegree = 0},
+                  {.channel = (int32_t)AudioChannelLayout::CHANNEL_FRONT_RIGHT,
+                   .azimuthDegree = 90,
+                   .elevationDegree = 0}};
+    }
+    return angles;
+}
+
+IEffect::Status BundleContext::lvmProcess(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    int64_t inputFrameCount = getCommon().input.frameCount;
+    int64_t outputFrameCount = getCommon().output.frameCount;
+    RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+    int isDataAvailable = true;
+
+    auto frameSize = getInputFrameSize();
+    RETURN_VALUE_IF(0 == frameSize, status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    if ((mEffectProcessCalled & 1 << int(mType)) != 0) {
+        const int undrainedEffects = mEffectInDrain & ~mEffectProcessCalled;
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+            LOG(DEBUG) << "Draining EQUALIZER";
+            mSamplesToExitCountEq = 0;
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+        }
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+            LOG(DEBUG) << "Draining BASS_BOOST";
+            mSamplesToExitCountBb = 0;
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+        }
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+            LOG(DEBUG) << "Draining VIRTUALIZER";
+            mSamplesToExitCountVirt = 0;
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+        }
+        if ((undrainedEffects & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+            LOG(DEBUG) << "Draining VOLUME";
+            --mNumberEffectsEnabled;
+            mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+        }
+    }
+    mEffectProcessCalled |= 1 << int(mType);
+    if (!mEnabled) {
+        switch (mType) {
+            case lvm::BundleEffectType::EQUALIZER:
+                if (mSamplesToExitCountEq > 0) {
+                    mSamplesToExitCountEq -= samples;
+                }
+                if (mSamplesToExitCountEq <= 0) {
+                    isDataAvailable = false;
+                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::EQUALIZER)) != 0) {
+                        mNumberEffectsEnabled--;
+                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::EQUALIZER));
+                    }
+                    LOG(DEBUG) << "Effect_process() this is the last frame for EQUALIZER";
+                }
+                break;
+            case lvm::BundleEffectType::BASS_BOOST:
+                if (mSamplesToExitCountBb > 0) {
+                    mSamplesToExitCountBb -= samples;
+                }
+                if (mSamplesToExitCountBb <= 0) {
+                    isDataAvailable = false;
+                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::BASS_BOOST)) != 0) {
+                        mNumberEffectsEnabled--;
+                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::BASS_BOOST));
+                    }
+                    LOG(DEBUG) << "Effect_process() this is the last frame for BASS_BOOST";
+                }
+                break;
+            case lvm::BundleEffectType::VIRTUALIZER:
+                if (mSamplesToExitCountVirt > 0) {
+                    mSamplesToExitCountVirt -= samples;
+                }
+                if (mSamplesToExitCountVirt <= 0) {
+                    isDataAvailable = false;
+                    if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VIRTUALIZER)) != 0) {
+                        mNumberEffectsEnabled--;
+                        mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VIRTUALIZER));
+                    }
+                    LOG(DEBUG) << "Effect_process() this is the last frame for VIRTUALIZER";
+                }
+                break;
+            case lvm::BundleEffectType::VOLUME:
+                isDataAvailable = false;
+                if ((mEffectInDrain & 1 << int(lvm::BundleEffectType::VOLUME)) != 0) {
+                    mNumberEffectsEnabled--;
+                    mEffectInDrain &= ~(1 << int(lvm::BundleEffectType::VOLUME));
+                }
+                LOG(DEBUG) << "Effect_process() LVM_VOLUME Effect is not enabled";
+                break;
+        }
+    }
+    if (isDataAvailable) {
+        mNumberEffectsCalled++;
+    }
+    bool accumulate = false;
+    if (mNumberEffectsCalled >= mNumberEffectsEnabled) {
+        // We expect the # effects called to be equal to # effects enabled in sequence (including
+        // draining effects).  Warn if this is not the case due to inconsistent calls.
+        ALOGW_IF(mNumberEffectsCalled > mNumberEffectsEnabled,
+                 "%s Number of effects called %d is greater than number of effects enabled %d",
+                 __func__, mNumberEffectsCalled, mNumberEffectsEnabled);
+        mEffectProcessCalled = 0;  // reset our consistency check.
+        if (!isDataAvailable) {
+            LOG(DEBUG) << "Effect_process() processing last frame";
+        }
+        mNumberEffectsCalled = 0;
+        LVM_UINT16 frames = samples * sizeof(float) / frameSize;
+        float* outTmp = (accumulate ? getWorkBuffer() : out);
+        /* Process the samples */
+        LVM_ReturnStatus_en lvmStatus;
+        {
+            std::lock_guard lg(mMutex);
+            lvmStatus = LVM_Process(mInstance, in, outTmp, frames, 0);
+            if (lvmStatus != LVM_SUCCESS) {
+                LOG(ERROR) << __func__ << lvmStatus;
+                return {EX_UNSUPPORTED_OPERATION, 0, 0};
+            }
+            if (accumulate) {
+                for (int i = 0; i < samples; i++) {
+                    out[i] += outTmp[i];
+                }
+            }
+        }
+    } else {
+        for (int i = 0; i < samples; i++) {
+            if (accumulate) {
+                out[i] += in[i];
+            } else {
+                out[i] = in[i];
+            }
+        }
+    }
+    LOG(DEBUG) << __func__ << " done processing";
+    return {STATUS_OK, samples, samples};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleContext.h b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
new file mode 100644
index 0000000..47d5e5a
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleContext.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <array>
+#include <cstddef>
+
+#include "BundleTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class BundleContext final : public EffectContext {
+  public:
+    BundleContext(int statusDepth, const Parameter::Common& common,
+                  const lvm::BundleEffectType& type)
+        : EffectContext(statusDepth, common), mType(type) {
+        LOG(DEBUG) << __func__ << type;
+    }
+    ~BundleContext() override {
+        LOG(DEBUG) << __func__;
+        deInit();
+    }
+
+    RetCode init();
+    void deInit();
+    lvm::BundleEffectType getBundleType() const { return mType; }
+
+    RetCode enable();
+    RetCode enableOperatingMode();
+    RetCode disable();
+    RetCode disableOperatingMode();
+
+    void setSampleRate(const int sampleRate) { mSampleRate = sampleRate; }
+    int getSampleRate() const { return mSampleRate; }
+
+    void setChannelMask(const aidl::android::media::audio::common::AudioChannelLayout& chMask) {
+        mChMask = chMask;
+    }
+    aidl::android::media::audio::common::AudioChannelLayout getChannelMask() const {
+        return mChMask;
+    }
+    bool isDeviceSupportedBassBoost(
+            const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
+                    devices);
+    bool isDeviceSupportedVirtualizer(
+            const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
+                    devices);
+    bool isConfigSupportedVirtualizer(
+            size_t channelCount,
+            const aidl::android::media::audio::common::AudioDeviceDescription& device);
+
+    RetCode setOutputDevice(
+            const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& devices)
+            override;
+
+    RetCode setEqualizerPreset(const std::size_t presetIdx);
+    int getEqualizerPreset() const { return mCurPresetIdx; }
+    RetCode setEqualizerBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels);
+    std::vector<Equalizer::BandLevel> getEqualizerBandLevels() const;
+
+    std::vector<int32_t> getEqualizerCenterFreqs();
+
+    RetCode setBassBoostStrength(int strength);
+    int getBassBoostStrength() const { return mBassStrengthSaved; }
+
+    RetCode setVolumeLevel(int level);
+    int getVolumeLevel() const;
+
+    RetCode setVolumeMute(bool mute);
+    int getVolumeMute() const { return mMuteEnabled; }
+
+    RetCode setVirtualizerStrength(int strength);
+    int getVirtualizerStrength() const { return mVirtStrengthSaved; }
+
+    RetCode setForcedDevice(
+            const ::aidl::android::media::audio::common::AudioDeviceDescription& device);
+    aidl::android::media::audio::common::AudioDeviceDescription getForcedDevice() const {
+        return mForceDevice;
+    }
+    std::vector<Virtualizer::ChannelAngle> getSpeakerAngles(
+            const Virtualizer::SpeakerAnglesPayload payload);
+
+    RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
+    Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+    IEffect::Status processEffect(float* in, float* out, int sampleToProcess);
+
+  private:
+    std::mutex mMutex;
+    const lvm::BundleEffectType mType;
+    bool mEnabled = false;
+    LVM_Handle_t mInstance GUARDED_BY(mMutex);
+
+    aidl::android::media::audio::common::AudioDeviceDescription mVirtualizerForcedDevice;
+    aidl::android::media::audio::common::AudioChannelLayout mChMask;
+
+    int mSampleRate = LVM_FS_44100;
+    int mSamplesPerSecond = 0;
+    int mSamplesToExitCountEq = 0;
+    int mSamplesToExitCountBb = 0;
+    int mSamplesToExitCountVirt = 0;
+    int mFrameCount = 0;
+
+    /* Bitmask whether drain is in progress due to disabling the effect.
+       The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+    int mEffectInDrain = 0;
+
+    /* Bitmask whether process() was called for a particular effect.
+       The corresponding bit to an effect is set by 1 << lvm_effect_en. */
+    int mEffectProcessCalled = 0;
+    int mNumberEffectsEnabled = 0;
+    int mNumberEffectsCalled = 0;
+    bool mFirstVolume = true;
+    // Bass
+    bool mBassTempDisabled = false;
+    int mBassStrengthSaved = 0;
+    // Equalizer
+    int mCurPresetIdx = lvm::PRESET_CUSTOM; /* Current preset being used */
+    std::array<int, lvm::MAX_NUM_BANDS> mBandGaindB;
+    // Virtualizer
+    int mVirtStrengthSaved = 0; /* Conversion between Get/Set */
+    bool mVirtualizerTempDisabled = false;
+    ::aidl::android::media::audio::common::AudioDeviceDescription mForceDevice;
+    // Volume
+    int mLevelSaved = 0; /* for when mute is set, level must be saved */
+    int mVolume = 0;
+    bool mMuteEnabled = false; /* Must store as mute = -96dB level */
+
+    void initControlParameter(LVM_ControlParams_t& params) const;
+    void initHeadroomParameter(LVM_HeadroomParams_t& params) const;
+    RetCode limitLevel();
+    int16_t VolToDb(uint32_t vol) const;
+    LVM_INT16 LVC_ToDB_s32Tos16(LVM_INT32 Lin_fix) const;
+    RetCode updateControlParameter(const std::vector<Equalizer::BandLevel>& bandLevels);
+    bool isBandLevelIndexInRange(const std::vector<Equalizer::BandLevel>& bandLevels) const;
+    static LVM_EQNB_BandDef_t* getDefaultEqualizerBandDefs();
+    static LVM_HeadroomBandDef_t* getDefaultEqualizerHeadroomBanDefs();
+};
+
+}  // namespace aidl::android::hardware::audio::effect
+
diff --git a/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
new file mode 100644
index 0000000..b3371a3
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/BundleTypes.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <array>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "effect-impl/EffectTypes.h"
+#include "LVM.h"
+
+namespace aidl::android::hardware::audio::effect {
+namespace lvm {
+
+constexpr inline size_t MAX_NUM_PRESETS = 10;
+constexpr inline size_t MAX_NUM_BANDS = 5;
+constexpr inline size_t MAX_CALL_SIZE = 256;
+constexpr inline int BASS_BOOST_CUP_LOAD_ARM9E = 150;   // Expressed in 0.1 MIPS
+constexpr inline int VIRTUALIZER_CUP_LOAD_ARM9E = 120;  // Expressed in 0.1 MIPS
+constexpr inline int EQUALIZER_CUP_LOAD_ARM9E = 220;    // Expressed in 0.1 MIPS
+constexpr inline int VOLUME_CUP_LOAD_ARM9E = 0;         // Expressed in 0.1 MIPS
+constexpr inline int BUNDLE_MEM_USAGE = 25;             // Expressed in kB
+constexpr inline int PRESET_CUSTOM = -1;
+
+static const std::vector<Equalizer::BandFrequency> kEqBandFrequency = {{0, 30000, 120000},
+                                                                       {1, 120001, 460000},
+                                                                       {2, 460001, 1800000},
+                                                                       {3, 1800001, 7000000},
+                                                                       {4, 7000001, 20000000}};
+
+/*
+Frequencies in Hz
+Note: If these frequencies change, please update LimitLevel values accordingly.
+*/
+constexpr inline std::array<uint16_t, MAX_NUM_BANDS> kPresetsFrequencies = {60, 230, 910, 3600,
+                                                                            14000};
+
+/* Q factor multiplied by 100 */
+constexpr inline std::array<uint16_t, MAX_NUM_BANDS> kPresetsQFactors = {96, 96, 96, 96, 96};
+
+constexpr inline std::array<std::array<int16_t, MAX_NUM_BANDS>, MAX_NUM_PRESETS> kSoftPresets = {
+        {{3, 0, 0, 0, 3},    /* Normal Preset */
+         {5, 3, -2, 4, 4},   /* Classical Preset */
+         {6, 0, 2, 4, 1},    /* Dance Preset */
+         {0, 0, 0, 0, 0},    /* Flat Preset */
+         {3, 0, 0, 2, -1},   /* Folk Preset */
+         {4, 1, 9, 3, 0},    /* Heavy Metal Preset */
+         {5, 3, 0, 1, 3},    /* Hip Hop Preset */
+         {4, 2, -2, 2, 5},   /* Jazz Preset */
+         {-1, 2, 5, 1, -2},  /* Pop Preset */
+         {5, 3, -1, 3, 5}}}; /* Rock Preset */
+
+static const std::vector<Equalizer::Preset> kEqPresets = {
+        {0, "Normal"},      {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
+        {5, "Heavy Metal"}, {6, "Hip Hop"},   {7, "Jazz"},  {8, "Pop"},  {9, "Rock"}};
+
+
+const std::vector<Range::EqualizerRange> kEqRanges = {
+        MAKE_RANGE(Equalizer, preset, 0, MAX_NUM_PRESETS - 1),
+        MAKE_RANGE(Equalizer, bandLevels,
+                   std::vector<Equalizer::BandLevel>{
+                           Equalizer::BandLevel({.index = 0, .levelMb = -15})},
+                   std::vector<Equalizer::BandLevel>{
+                           Equalizer::BandLevel({.index = MAX_NUM_BANDS - 1, .levelMb = 15})}),
+        /* capability definition */
+        MAKE_RANGE(Equalizer, bandFrequencies, kEqBandFrequency, kEqBandFrequency),
+        MAKE_RANGE(Equalizer, presets, kEqPresets, kEqPresets),
+        /* get only parameters with range min > max */
+        MAKE_RANGE(Equalizer, centerFreqMh, std::vector<int>({1}), std::vector<int>({}))};
+static const Capability kEqCap = {.range = kEqRanges};
+static const std::string kEqualizerEffectName = "EqualizerBundle";
+static const Descriptor kEqualizerDesc = {
+        .common = {.id = {.type = getEffectTypeUuidEqualizer(),
+                          .uuid = getEffectImplUuidEqualizerBundle(),
+                          .proxy = getEffectImplUuidEqualizerProxy()},
+
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = kEqualizerEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kEqCap};
+
+static const int mMaxStrengthSupported = 1000;
+static const std::vector<Range::BassBoostRange> kBassBoostRanges = {
+        MAKE_RANGE(BassBoost, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kBassBoostCap = {.range = kBassBoostRanges};
+static const std::string kBassBoostEffectName = "Dynamic Bass Boost";
+static const Descriptor kBassBoostDesc = {
+        .common = {.id = {.type = getEffectTypeUuidBassBoost(),
+                          .uuid = getEffectImplUuidBassBoostBundle(),
+                          .proxy = getEffectImplUuidBassBoostProxy()},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL,
+                             .deviceIndication = true},
+                   .cpuLoad = BASS_BOOST_CUP_LOAD_ARM9E,
+                   .memoryUsage = BUNDLE_MEM_USAGE,
+                   .name = kBassBoostEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kBassBoostCap};
+
+static const std::vector<Range::VirtualizerRange> kVirtualizerRanges = {
+        MAKE_RANGE(Virtualizer, strengthPm, 0, mMaxStrengthSupported)};
+static const Capability kVirtualizerCap = {.range = kVirtualizerRanges};
+static const std::string kVirtualizerEffectName = "Virtualizer";
+
+static const Descriptor kVirtualizerDesc = {
+        .common = {.id = {.type = getEffectTypeUuidVirtualizer(),
+                          .uuid = getEffectImplUuidVirtualizerBundle(),
+                          .proxy = getEffectImplUuidVirtualizerProxy()},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL,
+                             .deviceIndication = true},
+                   .cpuLoad = VIRTUALIZER_CUP_LOAD_ARM9E,
+                   .memoryUsage = BUNDLE_MEM_USAGE,
+                   .name = kVirtualizerEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kVirtualizerCap};
+
+static const std::vector<Range::VolumeRange> kVolumeRanges = {
+        MAKE_RANGE(Volume, levelDb, -9600, 0)};
+static const Capability kVolumeCap = {.range = kVolumeRanges};
+static const std::string kVolumeEffectName = "Volume";
+static const Descriptor kVolumeDesc = {
+        .common = {.id = {.type = getEffectTypeUuidVolume(),
+                          .uuid = getEffectImplUuidVolumeBundle(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL},
+                   .cpuLoad = VOLUME_CUP_LOAD_ARM9E,
+                   .memoryUsage = BUNDLE_MEM_USAGE,
+                   .name = kVolumeEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kVolumeCap};
+
+/* The following tables have been computed using the actual levels measured by the output of
+ * white noise or pink noise (IEC268-1) for the EQ and BassBoost Effects. These are estimates of
+ * the actual energy that 'could' be present in the given band.
+ * If the frequency values in EQNB_5BandPresetsFrequencies change, these values might need to be
+ * updated.
+ */
+constexpr inline std::array<float, MAX_NUM_BANDS> kBandEnergyCoefficient = {7.56, 9.69, 9.59, 7.37,
+                                                                            2.88};
+
+constexpr inline std::array<float, MAX_NUM_BANDS - 1> kBandEnergyCrossCoefficient = {126.0, 115.0,
+                                                                                     125.0, 104.0};
+
+constexpr inline std::array<float, MAX_NUM_BANDS> kBassBoostEnergyCrossCoefficient = {
+        221.21, 208.10, 28.16, 0.0, 0.0};
+
+constexpr inline float kBassBoostEnergyCoefficient = 9.00;
+
+constexpr inline float kVirtualizerContribution = 1.9;
+
+enum class BundleEffectType {
+    BASS_BOOST,
+    VIRTUALIZER,
+    EQUALIZER,
+    VOLUME,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const BundleEffectType& type) {
+    switch (type) {
+        case BundleEffectType::BASS_BOOST:
+            return out << "BASS_BOOST";
+        case BundleEffectType::VIRTUALIZER:
+            return out << "VIRTUALIZER";
+        case BundleEffectType::EQUALIZER:
+            return out << "EQUALIZER";
+        case BundleEffectType::VOLUME:
+            return out << "VOLUME";
+    }
+    return out << "EnumBundleEffectTypeError";
+}
+
+inline std::ostream& operator<<(std::ostream& out, const LVM_ReturnStatus_en& status) {
+    switch (status) {
+        case LVM_SUCCESS:
+            return out << "LVM_SUCCESS";
+        case LVM_ALIGNMENTERROR:
+            return out << "LVM_ALIGNMENTERROR";
+        case LVM_NULLADDRESS:
+            return out << "LVM_NULLADDRESS";
+        case LVM_OUTOFRANGE:
+            return out << "LVM_OUTOFRANGE";
+        case LVM_INVALIDNUMSAMPLES:
+            return out << "LVM_INVALIDNUMSAMPLES";
+        case LVM_WRONGAUDIOTIME:
+            return out << "LVM_WRONGAUDIOTIME";
+        case LVM_ALGORITHMDISABLED:
+            return out << "LVM_ALGORITHMDISABLED";
+        case LVM_ALGORITHMPSA:
+            return out << "LVM_ALGORITHMPSA";
+        case LVM_RETURNSTATUS_DUMMY:
+            return out << "LVM_RETURNSTATUS_DUMMY";
+    }
+    return out << "EnumLvmRetStatusError";
+}
+
+#define GOTO_IF_LVM_ERROR(status, tag, log)                                       \
+    do {                                                                          \
+        LVM_ReturnStatus_en temp = (status);                                      \
+        if (temp != LVM_SUCCESS) {                                                \
+            LOG(ERROR) << __func__ << " return status: " << temp << " " << (log); \
+            goto tag;                                                             \
+        }                                                                         \
+    } while (0)
+
+}  // namespace lvm
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
new file mode 100644
index 0000000..cd9fb60
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BundleTypes.h"
+#define LOG_TAG "EffectBundleAidl"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+#include <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
+
+#include "EffectBundleAidl.h"
+#include <LVM.h>
+#include <limits.h>
+
+using aidl::android::hardware::audio::effect::getEffectImplUuidBassBoostBundle;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectBundleAidl;
+using aidl::android::hardware::audio::effect::getEffectImplUuidEqualizerBundle;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::getEffectImplUuidVirtualizerBundle;
+using aidl::android::hardware::audio::effect::getEffectImplUuidVolumeBundle;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isUuidSupported(const AudioUuid* uuid) {
+    return (*uuid == getEffectImplUuidBassBoostBundle() ||
+            *uuid == getEffectImplUuidEqualizerBundle() ||
+            *uuid == getEffectImplUuidVirtualizerBundle() ||
+            *uuid == getEffectImplUuidVolumeBundle());
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (uuid == nullptr || !isUuidSupported(uuid)) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<EffectBundleAidl>(*uuid);
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || !isUuidSupported(in_impl_uuid)) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (*in_impl_uuid == getEffectImplUuidEqualizerBundle()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kEqualizerDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidBassBoostBundle()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm:: kBassBoostDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidVirtualizerBundle()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVirtualizerDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidVolumeBundle()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kVolumeDesc;
+    }
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectBundleAidl::EffectBundleAidl(const AudioUuid& uuid) {
+    LOG(DEBUG) << __func__ << uuid.toString();
+    if (uuid == getEffectImplUuidEqualizerBundle()) {
+        mType = lvm::BundleEffectType::EQUALIZER;
+        mDescriptor = &lvm::kEqualizerDesc;
+        mEffectName = &lvm::kEqualizerEffectName;
+    } else if (uuid == getEffectImplUuidBassBoostBundle()) {
+        mType = lvm::BundleEffectType::BASS_BOOST;
+        mDescriptor = &lvm::kBassBoostDesc;
+        mEffectName = &lvm::kBassBoostEffectName;
+    } else if (uuid == getEffectImplUuidVirtualizerBundle()) {
+        mType = lvm::BundleEffectType::VIRTUALIZER;
+        mDescriptor = &lvm::kVirtualizerDesc;
+        mEffectName = &lvm::kVirtualizerEffectName;
+    } else if (uuid == getEffectImplUuidVolumeBundle()) {
+        mType = lvm::BundleEffectType::VOLUME;
+        mDescriptor = &lvm::kVolumeDesc;
+        mEffectName = &lvm::kVolumeEffectName;
+    } else {
+        LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+    }
+}
+
+EffectBundleAidl::~EffectBundleAidl() {
+    cleanUp();
+    LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << _aidl_return->toString();
+    *_aidl_return = *mDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterCommon(const Parameter& param) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = param.getTag();
+    switch (tag) {
+        case Parameter::common:
+            RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setCommFailed");
+            break;
+        case Parameter::deviceDescription:
+            RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+            break;
+        case Parameter::mode:
+            RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setModeFailed");
+            break;
+        case Parameter::source:
+            RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+            break;
+        case Parameter::volumeStereo:
+            RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+            break;
+        default: {
+            LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "commonParamNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterSpecific(const Parameter::Specific& specific) {
+    LOG(DEBUG) << __func__ << " specific " << specific.toString();
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = specific.getTag();
+    switch (tag) {
+        case Parameter::Specific::equalizer:
+            return setParameterEqualizer(specific);
+        case Parameter::Specific::bassBoost:
+            return setParameterBassBoost(specific);
+        case Parameter::Specific::virtualizer:
+            return setParameterVirtualizer(specific);
+        case Parameter::Specific::volume:
+            return setParameterVolume(specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "specificParamNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterEqualizer(const Parameter::Specific& specific) {
+    auto& eq = specific.get<Parameter::Specific::equalizer>();
+    RETURN_IF(!inRange(eq, lvm::kEqRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto eqTag = eq.getTag();
+    switch (eqTag) {
+        case Equalizer::preset:
+            RETURN_IF(mContext->setEqualizerPreset(eq.get<Equalizer::preset>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+            return ndk::ScopedAStatus::ok();
+        case Equalizer::bandLevels:
+            RETURN_IF(mContext->setEqualizerBandLevels(eq.get<Equalizer::bandLevels>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+            return ndk::ScopedAStatus::ok();
+        default:
+            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "eqTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterBassBoost(const Parameter::Specific& specific) {
+    auto& bb = specific.get<Parameter::Specific::bassBoost>();
+    RETURN_IF(!inRange(bb, lvm::kBassBoostRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto bbTag = bb.getTag();
+    switch (bbTag) {
+        case BassBoost::strengthPm: {
+            RETURN_IF(mContext->setBassBoostStrength(bb.get<BassBoost::strengthPm>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default:
+            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "bbTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVirtualizer(const Parameter::Specific& specific) {
+    auto& vr = specific.get<Parameter::Specific::virtualizer>();
+    RETURN_IF(!inRange(vr, lvm::kVirtualizerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto vrTag = vr.getTag();
+    switch (vrTag) {
+        case Virtualizer::strengthPm: {
+            RETURN_IF(mContext->setVirtualizerStrength(vr.get<Virtualizer::strengthPm>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setStrengthFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Virtualizer::device: {
+            RETURN_IF(mContext->setForcedDevice(vr.get<Virtualizer::device>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Virtualizer::speakerAngles:
+            FALLTHROUGH_INTENDED;
+        case Virtualizer::vendor: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(vrTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VirtualizerTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::setParameterVolume(const Parameter::Specific& specific) {
+    auto& vol = specific.get<Parameter::Specific::volume>();
+    RETURN_IF(!inRange(vol, lvm::kVolumeRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto volTag = vol.getTag();
+    switch (volTag) {
+        case Volume::levelDb: {
+            RETURN_IF(mContext->setVolumeLevel(vol.get<Volume::levelDb>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Volume::mute:
+            RETURN_IF(mContext->setVolumeMute(vol.get<Volume::mute>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setMuteFailed");
+            return ndk::ScopedAStatus::ok();
+        default:
+            LOG(ERROR) << __func__ << " unsupported parameter " << specific.toString();
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "volTagNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterSpecific(const Parameter::Id& id,
+                                                          Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+
+    switch (tag) {
+        case Parameter::Id::equalizerTag:
+            return getParameterEqualizer(id.get<Parameter::Id::equalizerTag>(), specific);
+        case Parameter::Id::bassBoostTag:
+            return getParameterBassBoost(id.get<Parameter::Id::bassBoostTag>(), specific);
+        case Parameter::Id::virtualizerTag:
+            return getParameterVirtualizer(id.get<Parameter::Id::virtualizerTag>(), specific);
+        case Parameter::Id::volumeTag:
+            return getParameterVolume(id.get<Parameter::Id::volumeTag>(), specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "wrongIdTag");
+    }
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterEqualizer(const Equalizer::Id& id,
+                                                           Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != Equalizer::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "EqualizerTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    Equalizer eqParam;
+
+    auto tag = id.get<Equalizer::Id::commonTag>();
+    switch (tag) {
+        case Equalizer::bandLevels: {
+            eqParam.set<Equalizer::bandLevels>(mContext->getEqualizerBandLevels());
+            break;
+        }
+        case Equalizer::preset: {
+            eqParam.set<Equalizer::preset>(mContext->getEqualizerPreset());
+            break;
+        }
+        case Equalizer::bandFrequencies: {
+            eqParam.set<Equalizer::bandFrequencies>(lvm::kEqBandFrequency);
+            break;
+        }
+        case Equalizer::presets: {
+            eqParam.set<Equalizer::presets>(lvm::kEqPresets);
+            break;
+        }
+        case Equalizer::centerFreqMh: {
+            eqParam.set<Equalizer::centerFreqMh>(mContext->getEqualizerCenterFreqs());
+            break;
+        }
+        case Equalizer::vendor: {
+            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "unsupportedTag");
+        }
+    }
+
+    specific->set<Parameter::Specific::equalizer>(eqParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterBassBoost(const BassBoost::Id& id,
+                                                           Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != BassBoost::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "BassBoostTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    BassBoost bbParam;
+
+    auto tag = id.get<BassBoost::Id::commonTag>();
+    switch (tag) {
+        case BassBoost::strengthPm: {
+            bbParam.set<BassBoost::strengthPm>(mContext->getBassBoostStrength());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "BassBoostTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::bassBoost>(bbParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVolume(const Volume::Id& id,
+                                                        Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != Volume::Id::commonTag, EX_ILLEGAL_ARGUMENT, "VolumeTagNotSupported");
+
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    Volume volParam;
+
+    auto tag = id.get<Volume::Id::commonTag>();
+    switch (tag) {
+        case Volume::levelDb: {
+            volParam.set<Volume::levelDb>(mContext->getVolumeLevel());
+            break;
+        }
+        case Volume::mute: {
+            volParam.set<Volume::mute>(mContext->getVolumeMute());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VolumeTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::volume>(volParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectBundleAidl::getParameterVirtualizer(const Virtualizer::Id& id,
+                                                             Parameter::Specific* specific) {
+    RETURN_IF((id.getTag() != Virtualizer::Id::commonTag) &&
+                      (id.getTag() != Virtualizer::Id::speakerAnglesPayload),
+              EX_ILLEGAL_ARGUMENT, "VirtualizerTagNotSupported");
+
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    Virtualizer vrParam;
+
+    if (id.getTag() == Virtualizer::Id::speakerAnglesPayload) {
+        auto angles = mContext->getSpeakerAngles(id.get<Virtualizer::Id::speakerAnglesPayload>());
+        Virtualizer param = Virtualizer::make<Virtualizer::speakerAngles>(angles);
+        specific->set<Parameter::Specific::virtualizer>(param);
+        return ndk::ScopedAStatus::ok();
+    }
+
+    auto tag = id.get<Virtualizer::Id::commonTag>();
+    switch (tag) {
+        case Virtualizer::strengthPm: {
+            vrParam.set<Virtualizer::strengthPm>(mContext->getVirtualizerStrength());
+            break;
+        }
+        case Virtualizer::device: {
+            vrParam.set<Virtualizer::device>(mContext->getForcedDevice());
+            break;
+        }
+        case Virtualizer::speakerAngles:
+            FALLTHROUGH_INTENDED;
+        case Virtualizer::vendor: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VirtualizerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::virtualizer>(vrParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectBundleAidl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+    } else {
+        // GlobalSession is a singleton
+        mContext = GlobalSession::getGlobalSession().createSession(mType, 1 /* statusFmqDepth */,
+                                                                   common);
+    }
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectBundleAidl::getContext() {
+    return mContext;
+}
+
+RetCode EffectBundleAidl::releaseContext() {
+    if (mContext) {
+        GlobalSession::getGlobalSession().releaseSession(mType, mContext->getSessionId());
+        mContext.reset();
+    }
+    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};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
new file mode 100644
index 0000000..ec1abe8
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/EffectBundleAidl.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+#include <functional>
+#include <map>
+#include <memory>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android-base/logging.h>
+
+#include "effect-impl/EffectImpl.h"
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+#include "GlobalSession.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectBundleAidl final : public EffectImpl {
+  public:
+    explicit EffectBundleAidl(const AudioUuid& uuid);
+    ~EffectBundleAidl() override;
+
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterCommon(const Parameter& param) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
+    RetCode releaseContext() override;
+
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+    std::string getEffectName() override { return *mEffectName; }
+
+  private:
+    std::shared_ptr<BundleContext> mContext;
+    const Descriptor* mDescriptor;
+    const std::string* mEffectName;
+    lvm::BundleEffectType mType = lvm::BundleEffectType::EQUALIZER;
+
+    IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+
+    ndk::ScopedAStatus setParameterBassBoost(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Id& id,
+                                             Parameter::Specific* specific);
+
+    ndk::ScopedAStatus setParameterEqualizer(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Id& id,
+                                             Parameter::Specific* specific);
+    ndk::ScopedAStatus setParameterVolume(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterVolume(const Volume::Id& id, Parameter::Specific* specific);
+    ndk::ScopedAStatus setParameterVirtualizer(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Id& id,
+                                               Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
new file mode 100644
index 0000000..d31763b
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Aidl/GlobalSession.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+
+#include "BundleContext.h"
+#include "BundleTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * @brief Maintain all effect bundle sessions.
+ *
+ * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
+ * bundle implementation.
+ */
+class GlobalSession {
+  public:
+    static GlobalSession& getGlobalSession() {
+        static GlobalSession instance;
+        return instance;
+    }
+
+    bool isSessionIdExist(int sessionId) {
+        std::lock_guard lg(mMutex);
+        return mSessionMap.count(sessionId);
+    }
+
+    static bool findBundleTypeInList(std::vector<std::shared_ptr<BundleContext>>& list,
+                                     const lvm::BundleEffectType& type, bool remove = false) {
+        auto itor = std::find_if(list.begin(), list.end(),
+                                  [type](const std::shared_ptr<BundleContext>& bundle) {
+                                      return bundle ? bundle->getBundleType() == type : false;
+                                  });
+        if (itor == list.end()) {
+            return false;
+        }
+        if (remove && *itor) {
+            (*itor)->deInit();
+            list.erase(itor);
+        }
+        return true;
+    }
+
+    /**
+     * Create a certain type of BundleContext in shared_ptr container, each session must not have
+     * more than one session for each type.
+     */
+    std::shared_ptr<BundleContext> createSession(const lvm::BundleEffectType& type, int statusDepth,
+                                                 const Parameter::Common& common) {
+        int sessionId = common.session;
+        LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
+        std::lock_guard lg(mMutex);
+        if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_BUNDLE_SESSIONS) {
+            LOG(ERROR) << __func__ << " exceed max bundle session";
+            return nullptr;
+        }
+
+        if (mSessionMap.count(sessionId)) {
+            if (findBundleTypeInList(mSessionMap[sessionId], type)) {
+                LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
+                return nullptr;
+            }
+        }
+
+        auto& list = mSessionMap[sessionId];
+        auto context = std::make_shared<BundleContext>(statusDepth, common, type);
+        RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
+
+        RetCode ret = context->init();
+        if (RetCode::SUCCESS != ret) {
+            LOG(ERROR) << __func__ << " context init ret " << ret;
+            return nullptr;
+        }
+        list.push_back(context);
+        return context;
+    }
+
+    void releaseSession(const lvm::BundleEffectType& type, int sessionId) {
+        LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
+        std::lock_guard lg(mMutex);
+        if (mSessionMap.count(sessionId)) {
+            auto& list = mSessionMap[sessionId];
+            if (!findBundleTypeInList(list, type, true /* remove */)) {
+                LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
+                return;
+            }
+            if (list.size() == 0) {
+                mSessionMap.erase(sessionId);
+            }
+        }
+    }
+
+  private:
+    // Lock for mSessionMap access.
+    std::mutex mMutex;
+    // Max session number supported.
+    static constexpr int MAX_BUNDLE_SESSIONS = 32;
+    std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<BundleContext>>>
+            mSessionMap GUARDED_BY(mMutex);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Android.bp b/media/libeffects/lvm/wrapper/Android.bp
index 1287514..fa300d2 100644
--- a/media/libeffects/lvm/wrapper/Android.bp
+++ b/media/libeffects/lvm/wrapper/Android.bp
@@ -100,3 +100,66 @@
         integer_overflow: true,
     },
 }
+
+cc_library_shared {
+    name: "libbundleaidl",
+    srcs: [
+        "Aidl/BundleContext.cpp",
+        "Aidl/EffectBundleAidl.cpp",
+        ":effectCommonFile",
+    ],
+    static_libs: ["libmusicbundle"],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    local_include_dirs: ["Aidl"],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    cflags: [
+        "-Wthread-safety",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
+
+cc_library_shared {
+    name: "libreverbaidl",
+    srcs: [
+        "Reverb/aidl/ReverbContext.cpp",
+        "Reverb/aidl/EffectReverb.cpp",
+        ":effectCommonFile",
+    ],
+    static_libs: ["libreverb"],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    local_include_dirs: ["Reverb/aidl"],
+    header_libs: [
+        "libaudioeffects",
+        "libhardware_headers",
+    ],
+    shared_libs: [
+        "libbase",
+        "libaudioutils",
+        "libcutils",
+        "liblog",
+    ],
+    cflags: [
+        "-Wthread-safety",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
new file mode 100644
index 0000000..73141b6
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.cpp
@@ -0,0 +1,399 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ReverbTypes.h"
+#define LOG_TAG "EffectReverb"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+#include <audio_effects/effect_bassboost.h>
+#include <audio_effects/effect_equalizer.h>
+#include <audio_effects/effect_virtualizer.h>
+
+#include "EffectReverb.h"
+#include <limits.h>
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAuxEnvReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAuxPresetReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidInsertEnvReverb;
+using aidl::android::hardware::audio::effect::getEffectImplUuidInsertPresetReverb;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isReverbUuidSupported(const AudioUuid* uuid) {
+    return (*uuid == getEffectImplUuidAuxEnvReverb() ||
+            *uuid == getEffectImplUuidAuxPresetReverb() ||
+            *uuid == getEffectImplUuidInsertEnvReverb() ||
+            *uuid == getEffectImplUuidInsertPresetReverb());
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (uuid == nullptr || !isReverbUuidSupported(uuid)) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<EffectReverb>(*uuid);
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (*in_impl_uuid == getEffectImplUuidAuxEnvReverb()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kAuxEnvReverbDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidInsertEnvReverb()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kInsertEnvReverbDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidAuxPresetReverb()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kAuxPresetReverbDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidInsertPresetReverb()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::lvm::kInsertPresetReverbDesc;
+    } else {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectReverb::EffectReverb(const AudioUuid& uuid) {
+    LOG(DEBUG) << __func__ << uuid.toString();
+    if (uuid == getEffectImplUuidAuxEnvReverb()) {
+        mType = lvm::ReverbEffectType::AUX_ENV;
+        mDescriptor = &lvm::kAuxEnvReverbDesc;
+        mEffectName = &lvm::kAuxEnvReverbEffectName;
+    } else if (uuid == getEffectImplUuidInsertEnvReverb()) {
+        mType = lvm::ReverbEffectType::INSERT_ENV;
+        mDescriptor = &lvm::kInsertEnvReverbDesc;
+        mEffectName = &lvm::kInsertEnvReverbEffectName;
+    } else if (uuid == getEffectImplUuidAuxPresetReverb()) {
+        mType = lvm::ReverbEffectType::AUX_PRESET;
+        mDescriptor = &lvm::kAuxPresetReverbDesc;
+        mEffectName = &lvm::kAuxPresetReverbEffectName;
+    } else if (uuid == getEffectImplUuidInsertPresetReverb()) {
+        mType = lvm::ReverbEffectType::INSERT_PRESET;
+        mDescriptor = &lvm::kInsertPresetReverbDesc;
+        mEffectName = &lvm::kInsertPresetReverbEffectName;
+    } else {
+        LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+    }
+}
+
+EffectReverb::~EffectReverb() {
+    cleanUp();
+    LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectReverb::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << _aidl_return->toString();
+    *_aidl_return = *mDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectReverb::setParameterSpecific(const Parameter::Specific& specific) {
+    LOG(DEBUG) << __func__ << " specific " << specific.toString();
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = specific.getTag();
+    switch (tag) {
+        case Parameter::Specific::presetReverb:
+            return setParameterPresetReverb(specific);
+        case Parameter::Specific::environmentalReverb:
+            return setParameterEnvironmentalReverb(specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "specificParamNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectReverb::setParameterPresetReverb(const Parameter::Specific& specific) {
+    auto& prParam = specific.get<Parameter::Specific::presetReverb>();
+    RETURN_IF(!inRange(prParam, lvm::kPresetReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto tag = prParam.getTag();
+
+    switch (tag) {
+        case PresetReverb::preset: {
+            RETURN_IF(mContext->setPresetReverbPreset(prParam.get<PresetReverb::preset>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setPresetFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "PresetReverbTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectReverb::setParameterEnvironmentalReverb(
+        const Parameter::Specific& specific) {
+    auto& erParam = specific.get<Parameter::Specific::environmentalReverb>();
+    RETURN_IF(!inRange(erParam, lvm::kEnvReverbRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto tag = erParam.getTag();
+
+    switch (tag) {
+        case EnvironmentalReverb::roomLevelMb: {
+            RETURN_IF(mContext->setEnvironmentalReverbRoomLevel(
+                              erParam.get<EnvironmentalReverb::roomLevelMb>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setRoomLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::roomHfLevelMb: {
+            RETURN_IF(
+                    mContext->setEnvironmentalReverbRoomHfLevel(
+                            erParam.get<EnvironmentalReverb::roomHfLevelMb>()) != RetCode::SUCCESS,
+                    EX_ILLEGAL_ARGUMENT, "setRoomHfLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::decayTimeMs: {
+            RETURN_IF(mContext->setEnvironmentalReverbDecayTime(
+                              erParam.get<EnvironmentalReverb::decayTimeMs>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDecayTimeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::decayHfRatioPm: {
+            RETURN_IF(
+                    mContext->setEnvironmentalReverbDecayHfRatio(
+                            erParam.get<EnvironmentalReverb::decayHfRatioPm>()) != RetCode::SUCCESS,
+                    EX_ILLEGAL_ARGUMENT, "setDecayHfRatioFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::reflectionsLevelMb: {
+            RETURN_IF(mContext->setReflectionsLevel(
+                              erParam.get<EnvironmentalReverb::reflectionsLevelMb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setReflectionsLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::reflectionsDelayMs: {
+            RETURN_IF(mContext->setReflectionsDelay(
+                              erParam.get<EnvironmentalReverb::reflectionsDelayMs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setReflectionsDelayFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::levelMb: {
+            RETURN_IF(mContext->setEnvironmentalReverbLevel(
+                              erParam.get<EnvironmentalReverb::levelMb>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLevelFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::delayMs: {
+            RETURN_IF(mContext->setEnvironmentalReverbDelay(
+                              erParam.get<EnvironmentalReverb::delayMs>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDelayFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::diffusionPm: {
+            RETURN_IF(mContext->setEnvironmentalReverbDiffusion(
+                              erParam.get<EnvironmentalReverb::diffusionPm>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDiffusionFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::densityPm: {
+            RETURN_IF(mContext->setEnvironmentalReverbDensity(
+                              erParam.get<EnvironmentalReverb::densityPm>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setDensityFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case EnvironmentalReverb::bypass: {
+            RETURN_IF(mContext->setEnvironmentalReverbBypass(
+                              erParam.get<EnvironmentalReverb::bypass>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setBypassFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectReverb::getParameterSpecific(const Parameter::Id& id,
+                                                      Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+
+    switch (tag) {
+        case Parameter::Id::presetReverbTag:
+            return getParameterPresetReverb(id.get<Parameter::Id::presetReverbTag>(), specific);
+        case Parameter::Id::environmentalReverbTag:
+            return getParameterEnvironmentalReverb(id.get<Parameter::Id::environmentalReverbTag>(),
+                                                   specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "wrongIdTag");
+    }
+}
+
+ndk::ScopedAStatus EffectReverb::getParameterPresetReverb(const PresetReverb::Id& id,
+                                                          Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != PresetReverb::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "PresetReverbTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    PresetReverb prParam;
+    auto tag = id.get<PresetReverb::Id::commonTag>();
+    switch (tag) {
+        case PresetReverb::preset: {
+            prParam.set<PresetReverb::preset>(mContext->getPresetReverbPreset());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "PresetReverbTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::presetReverb>(prParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectReverb::getParameterEnvironmentalReverb(const EnvironmentalReverb::Id& id,
+                                                                 Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != EnvironmentalReverb::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "EnvironmentalReverbTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    EnvironmentalReverb erParam;
+
+    auto tag = id.get<EnvironmentalReverb::Id::commonTag>();
+    switch (tag) {
+        case EnvironmentalReverb::roomLevelMb: {
+            erParam.set<EnvironmentalReverb::roomLevelMb>(
+                    mContext->getEnvironmentalReverbRoomLevel());
+            break;
+        }
+        case EnvironmentalReverb::roomHfLevelMb: {
+            erParam.set<EnvironmentalReverb::roomHfLevelMb>(
+                    mContext->getEnvironmentalReverbRoomHfLevel());
+            break;
+        }
+        case EnvironmentalReverb::decayTimeMs: {
+            erParam.set<EnvironmentalReverb::decayTimeMs>(
+                    mContext->getEnvironmentalReverbDecayTime());
+            break;
+        }
+        case EnvironmentalReverb::decayHfRatioPm: {
+            erParam.set<EnvironmentalReverb::decayHfRatioPm>(
+                    mContext->getEnvironmentalReverbDecayHfRatio());
+            break;
+        }
+        case EnvironmentalReverb::reflectionsLevelMb: {
+            erParam.set<EnvironmentalReverb::reflectionsLevelMb>(mContext->getReflectionsLevel());
+            break;
+        }
+        case EnvironmentalReverb::reflectionsDelayMs: {
+            erParam.set<EnvironmentalReverb::reflectionsDelayMs>(mContext->getReflectionsDelay());
+            break;
+        }
+        case EnvironmentalReverb::levelMb: {
+            erParam.set<EnvironmentalReverb::levelMb>(mContext->getEnvironmentalReverbLevel());
+            break;
+        }
+        case EnvironmentalReverb::delayMs: {
+            erParam.set<EnvironmentalReverb::delayMs>(mContext->getEnvironmentalReverbDelay());
+            break;
+        }
+        case EnvironmentalReverb::diffusionPm: {
+            erParam.set<EnvironmentalReverb::diffusionPm>(
+                    mContext->getEnvironmentalReverbDiffusion());
+            break;
+        }
+        case EnvironmentalReverb::densityPm: {
+            erParam.set<EnvironmentalReverb::densityPm>(mContext->getEnvironmentalReverbDensity());
+            break;
+        }
+        case EnvironmentalReverb::bypass: {
+            erParam.set<EnvironmentalReverb::bypass>(mContext->getEnvironmentalReverbBypass());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "EnvironmentalReverbTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::environmentalReverb>(erParam);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectReverb::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+    } else {
+        mContext = std::make_shared<ReverbContext>(1 /* statusFmqDepth */, common, mType);
+    }
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectReverb::getContext() {
+    return mContext;
+}
+
+RetCode EffectReverb::releaseContext() {
+    if (mContext) {
+        mContext.reset();
+    }
+    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};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
new file mode 100644
index 0000000..d7d2bbd
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/EffectReverb.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+#include "ReverbContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectReverb final : public EffectImpl {
+  public:
+    explicit EffectReverb(const AudioUuid& uuid);
+    ~EffectReverb() override;
+
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
+    RetCode releaseContext() override;
+
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+    std::string getEffectName() override { return *mEffectName; }
+
+  private:
+    std::shared_ptr<ReverbContext> mContext;
+    const Descriptor* mDescriptor;
+    const std::string* mEffectName;
+    lvm::ReverbEffectType mType;
+
+    IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+
+    ndk::ScopedAStatus setParameterPresetReverb(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterPresetReverb(const PresetReverb::Id& id,
+                                                Parameter::Specific* specific);
+
+    ndk::ScopedAStatus setParameterEnvironmentalReverb(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Id& id,
+                                                       Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
new file mode 100644
index 0000000..79e67f2
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.cpp
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+
+#define LOG_TAG "ReverbContext"
+#include <android-base/logging.h>
+#include <Utils.h>
+
+#include "ReverbContext.h"
+#include "VectorArithmetic.h"
+#include "math.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+#define GOTO_IF_LVREV_ERROR(status, tag, log)                                     \
+    do {                                                                          \
+        LVREV_ReturnStatus_en temp = (status);                                    \
+        if (temp != LVREV_SUCCESS) {                                              \
+            LOG(ERROR) << __func__ << " return status: " << temp << " " << (log); \
+            goto tag;                                                             \
+        }                                                                         \
+    } while (0)
+
+RetCode ReverbContext::init() {
+    if (isPreset()) {
+        // force reloading preset at first call to process()
+        mPreset = PresetReverb::Presets::NONE;
+        mNextPreset = PresetReverb::Presets::NONE;
+    }
+
+    mVolume.left = kUnitVolume;
+    mVolume.right = kUnitVolume;
+    mPrevVolume.left = kUnitVolume;
+    mPrevVolume.right = kUnitVolume;
+    volumeMode = VOLUME_FLAT;
+
+    mSamplesToExitCount = kDefaultDecayTime * mCommon.input.base.sampleRate / 1000;
+
+    /* Saved strength is used to return the exact strength that was used in the set to the get
+     * because we map the original strength range of 0:1000 to 1:15, and this will avoid
+     * quantisation like effect when returning
+     */
+    mRoomLevel = lvm::kMinLevel;
+    mRoomHfLevel = 0;
+    mEnabled = LVM_FALSE;
+    mDecayTime = kDefaultDecayTime;
+    mDecayHfRatio = kDefaultDamping * 20;
+    mDensity = kDefaultRoomSize * 10;
+    mDiffusion = kDefaultDensity * 10;
+    mLevel = lvm::kMinLevel;
+
+    // allocate lvm reverb instance
+    LVREV_ReturnStatus_en status = LVREV_SUCCESS;
+    {
+        std::lock_guard lg(mMutex);
+        LVREV_InstanceParams_st params = {
+                .MaxBlockSize = lvm::kMaxCallSize,
+                // Max format, could be mono during process
+                .SourceFormat = LVM_STEREO,
+                .NumDelays = LVREV_DELAYLINES_4,
+        };
+        /* Init sets the instance handle */
+        status = LVREV_GetInstanceHandle(&mInstance, &params);
+        GOTO_IF_LVREV_ERROR(status, deinit, "LVREV_GetInstanceHandleFailed");
+
+        // set control
+        LVREV_ControlParams_st controlParams;
+        initControlParameter(controlParams);
+        status = LVREV_SetControlParameters(mInstance, &controlParams);
+        GOTO_IF_LVREV_ERROR(status, deinit, "LVREV_SetControlParametersFailed");
+    }
+
+    return RetCode::SUCCESS;
+
+deinit:
+    deInit();
+    return RetCode::ERROR_EFFECT_LIB_ERROR;
+}
+
+void ReverbContext::deInit() {
+    std::lock_guard lg(mMutex);
+    if (mInstance) {
+        LVREV_FreeInstance(mInstance);
+        mInstance = nullptr;
+    }
+}
+
+RetCode ReverbContext::enable() {
+    if (mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+    mEnabled = true;
+    mSamplesToExitCount = (mDecayTime * mCommon.input.base.sampleRate) / 1000;
+    // force no volume ramp for first buffer processed after enabling the effect
+    volumeMode = VOLUME_FLAT;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::disable() {
+    if (!mEnabled) return RetCode::ERROR_ILLEGAL_PARAMETER;
+    mEnabled = false;
+    return RetCode::SUCCESS;
+}
+
+bool ReverbContext::isAuxiliary() {
+    return (mType == lvm::ReverbEffectType::AUX_ENV || mType == lvm::ReverbEffectType::AUX_PRESET);
+}
+
+bool ReverbContext::isPreset() {
+    return (mType == lvm::ReverbEffectType::AUX_PRESET ||
+            mType == lvm::ReverbEffectType::INSERT_PRESET);
+}
+
+RetCode ReverbContext::setVolumeStereo(const Parameter::VolumeStereo& volume) {
+    if (volumeMode == VOLUME_OFF) {
+        // force no volume ramp for first buffer processed after getting volume control
+        volumeMode = VOLUME_FLAT;
+    }
+    mVolumeStereo = volume;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setPresetReverbPreset(const PresetReverb::Presets& preset) {
+    mNextPreset = preset;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbRoomLevel(int roomLevel) {
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        // Sum of room and reverb level controls
+        // needs to subtract max levels for both room level and reverb level
+        int combinedLevel = (roomLevel + mLevel) - lvm::kMaxReverbLevel;
+        params.Level = convertLevel(combinedLevel);
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mRoomLevel = roomLevel;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbRoomHfLevel(int roomHfLevel) {
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.LPF = convertHfLevel(roomHfLevel);
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mRoomHfLevel = roomHfLevel;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDecayTime(int decayTime) {
+    int time = decayTime;
+    if (time > lvm::kMaxT60) {
+        time = lvm::kMaxT60;
+    }
+
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.T60 = (LVM_UINT16)time;
+        mSamplesToExitCount = (params.T60 * mCommon.input.base.sampleRate) / 1000;
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mDecayTime = time;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDecayHfRatio(int decayHfRatio) {
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.Damping = (LVM_INT16)(decayHfRatio / 20);
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mDecayHfRatio = decayHfRatio;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbLevel(int level) {
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        // Sum of room and reverb level controls
+        // needs to subtract max levels for both room level and level
+        int combinedLevel = (level + mRoomLevel) - lvm::kMaxReverbLevel;
+        params.Level = convertLevel(combinedLevel);
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mLevel = level;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDelay(int delay) {
+    mDelay = delay;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDiffusion(int diffusion) {
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.Density = (LVM_INT16)(diffusion / 10);
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mDiffusion = diffusion;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbDensity(int density) {
+    // Update Control Parameter
+    LVREV_ControlParams_st params;
+    {
+        std::lock_guard lg(mMutex);
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_GetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " getControlParamFailed");
+
+        params.RoomSize = (LVM_INT16)(((density * 99) / 1000) + 1);
+
+        RETURN_VALUE_IF(LVREV_SUCCESS != LVREV_SetControlParameters(mInstance, &params),
+                        RetCode::ERROR_EFFECT_LIB_ERROR, " setControlParamFailed");
+    }
+    mDensity = density;
+    return RetCode::SUCCESS;
+}
+
+RetCode ReverbContext::setEnvironmentalReverbBypass(bool bypass) {
+    mBypass = bypass;
+    return RetCode::SUCCESS;
+}
+
+void ReverbContext::loadPreset() {
+    // TODO: add delay when early reflections are implemented
+    mPreset = mNextPreset;
+
+    if (mPreset != PresetReverb::Presets::NONE) {
+        const t_reverb_settings preset = mReverbPresets[mPreset];
+        setEnvironmentalReverbRoomLevel(preset.roomLevel);
+        setEnvironmentalReverbRoomHfLevel(preset.roomHFLevel);
+        setEnvironmentalReverbDecayTime(preset.decayTime);
+        setEnvironmentalReverbDecayHfRatio(preset.decayHFRatio);
+        setEnvironmentalReverbLevel(preset.reverbLevel);
+        // reverbDelay
+        setEnvironmentalReverbDiffusion(preset.diffusion);
+        setEnvironmentalReverbDensity(preset.density);
+    }
+}
+
+void ReverbContext::initControlParameter(LVREV_ControlParams_st& params) {
+    /* Set the initial process parameters */
+    /* General parameters */
+    params.OperatingMode = LVM_MODE_ON;
+    params.SampleRate = LVM_FS_44100;
+    params.SourceFormat = (::aidl::android::hardware::audio::common::getChannelCount(
+                                   mCommon.input.base.channelMask) == 1
+                                   ? LVM_MONO
+                                   : LVM_STEREO);
+
+    if (!isAuxiliary() && params.SourceFormat == LVM_MONO) {
+        params.SourceFormat = LVM_STEREO;
+    }
+
+    /* Reverb parameters */
+    params.Level = kDefaultLevel;
+    params.LPF = kDefaultLPF;
+    params.HPF = kDefaultHPF;
+    params.T60 = kDefaultDecayTime;
+    params.Density = kDefaultDensity;
+    params.Damping = kDefaultDamping;
+    params.RoomSize = kDefaultRoomSize;
+}
+
+/*
+ * Convert level from OpenSL ES format to LVM format
+ *
+ *  @param level : level to be applied
+ */
+
+int ReverbContext::convertLevel(int level) {
+    for (int i = 0; i < kLevelMapping.size(); i++) {
+        if (level <= kLevelMapping[i]) {
+            return i;
+        }
+    }
+    return kDefaultLevel;
+}
+
+/*
+ * Convert level HF from OpenSL ES format to LVM format
+ *
+ * @param hfLevel : level to be applied
+ */
+
+int16_t ReverbContext::convertHfLevel(int hfLevel) {
+    for (auto lpfPair : kLPFMapping) {
+        if (hfLevel <= lpfPair.roomHf) {
+            return lpfPair.lpf;
+        }
+    }
+    return kDefaultLPF;
+}
+
+IEffect::Status ReverbContext::lvmProcess(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    int64_t inputFrameCount = getCommon().input.frameCount;
+    int64_t outputFrameCount = getCommon().output.frameCount;
+    RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+    RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    std::lock_guard lg(mMutex);
+
+    int channels = ::aidl::android::hardware::audio::common::getChannelCount(
+            mCommon.input.base.channelMask);
+    int outChannels = ::aidl::android::hardware::audio::common::getChannelCount(
+            mCommon.output.base.channelMask);
+    int frameCount = mCommon.input.frameCount;
+
+    // Reverb only effects the stereo channels in multichannel source.
+    if (channels < 1 || channels > LVM_MAX_CHANNELS) {
+        LOG(ERROR) << __func__ << " process invalid PCM channels " << channels;
+        return status;
+    }
+
+    std::vector<float> inFrames(samples);
+    std::vector<float> outFrames(frameCount * FCC_2);
+
+    if (isPreset() && mNextPreset != mPreset) {
+        loadPreset();
+    }
+
+    if (isAuxiliary()) {
+        inFrames.assign(in, in + samples);
+    } else {
+        // mono input is duplicated
+        if (channels >= FCC_2) {
+            for (int i = 0; i < frameCount; i++) {
+                inFrames[FCC_2 * i] = in[channels * i] * kSendLevel;
+                inFrames[FCC_2 * i + 1] = in[channels * i + 1] * kSendLevel;
+            }
+        } else {
+            for (int i = 0; i < frameCount; i++) {
+                inFrames[FCC_2 * i] = inFrames[FCC_2 * i + 1] = in[i] * kSendLevel;
+            }
+        }
+    }
+
+    if (isPreset() && mPreset == PresetReverb::Presets::NONE) {
+        std::fill(outFrames.begin(), outFrames.end(), 0);  // always stereo here
+    } else {
+        if (!mEnabled && mSamplesToExitCount > 0) {
+            std::fill(outFrames.begin(), outFrames.end(), 0);
+            LOG(VERBOSE) << "Zeroing " << channels << " samples per frame at the end of call ";
+        }
+
+        /* Process the samples, producing a stereo output */
+        LVREV_ReturnStatus_en lvrevStatus =
+                LVREV_Process(mInstance,        /* Instance handle */
+                              inFrames.data(),  /* Input buffer */
+                              outFrames.data(), /* Output buffer */
+                              frameCount);      /* Number of samples to read */
+        if (lvrevStatus != LVREV_SUCCESS) {
+            LOG(ERROR) << __func__ << lvrevStatus;
+            return {EX_UNSUPPORTED_OPERATION, 0, 0};
+        }
+    }
+    // Convert to 16 bits
+    if (isAuxiliary()) {
+        // nothing to do here
+    } else {
+        if (channels >= FCC_2) {
+            for (int i = 0; i < frameCount; i++) {
+                // Mix with dry input
+                outFrames[FCC_2 * i] += in[channels * i];
+                outFrames[FCC_2 * i + 1] += in[channels * i + 1];
+            }
+        } else {
+            for (int i = 0; i < frameCount; i++) {
+                // Mix with dry input
+                outFrames[FCC_2 * i] += in[i];
+                outFrames[FCC_2 * i + 1] += in[i];
+            }
+        }
+
+        // apply volume with ramp if needed
+        if (mVolume != mPrevVolume && volumeMode == VOLUME_RAMP) {
+            float vl = mPrevVolume.left;
+            float incl = (mVolume.left - vl) / frameCount;
+            float vr = mPrevVolume.right;
+            float incr = (mVolume.right - vr) / frameCount;
+
+            for (int i = 0; i < frameCount; i++) {
+                outFrames[FCC_2 * i] *= vl;
+                outFrames[FCC_2 * i + 1] *= vr;
+
+                vl += incl;
+                vr += incr;
+            }
+            mPrevVolume = mVolume;
+        } else if (volumeMode != VOLUME_OFF) {
+            if (mVolume.left != kUnitVolume || mVolume.right != kUnitVolume) {
+                for (int i = 0; i < frameCount; i++) {
+                    outFrames[FCC_2 * i] *= mVolume.left;
+                    outFrames[FCC_2 * i + 1] *= mVolume.right;
+                }
+            }
+            mPrevVolume = mVolume;
+            volumeMode = VOLUME_RAMP;
+        }
+    }
+
+    bool accumulate = false;
+    if (outChannels > 2) {
+        // Accumulate if required
+        if (accumulate) {
+            for (int i = 0; i < frameCount; i++) {
+                out[outChannels * i] += outFrames[FCC_2 * i];
+                out[outChannels * i + 1] += outFrames[FCC_2 * i + 1];
+            }
+        } else {
+            for (int i = 0; i < frameCount; i++) {
+                out[outChannels * i] = outFrames[FCC_2 * i];
+                out[outChannels * i + 1] = outFrames[FCC_2 * i + 1];
+            }
+        }
+        if (!isAuxiliary()) {
+            for (int i = 0; i < frameCount; i++) {
+                // channels and outChannels are expected to be same.
+                for (int j = FCC_2; j < outChannels; j++) {
+                    out[outChannels * i + j] = in[outChannels * i + j];
+                }
+            }
+        }
+    } else {
+        if (accumulate) {
+            if (outChannels == FCC_1) {
+                for (int i = 0; i < frameCount; i++) {
+                    out[i] += ((outFrames[i * FCC_2] + outFrames[i * FCC_2 + 1]) * 0.5f);
+                }
+            } else {
+                for (int i = 0; i < frameCount * FCC_2; i++) {
+                    out[i] += outFrames[i];
+                }
+            }
+        } else {
+            if (outChannels == FCC_1) {
+                From2iToMono_Float(outFrames.data(), out, frameCount);
+            } else {
+                for (int i = 0; i < frameCount * FCC_2; i++) {
+                    out[i] = outFrames[i];
+                }
+            }
+        }
+    }
+
+    LOG(DEBUG) << __func__ << " done processing";
+
+    if (!mEnabled && mSamplesToExitCount > 0) {
+        // signed - unsigned will trigger integer overflow if result becomes negative.
+        mSamplesToExitCount -= samples;
+    }
+
+    return {STATUS_OK, samples, outChannels * frameCount};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
new file mode 100644
index 0000000..9bb0b1a
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbContext.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <unordered_map>
+
+#include "ReverbTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum VolumeMode {
+    VOLUME_OFF,
+    VOLUME_FLAT,
+    VOLUME_RAMP,
+};
+
+struct LPFPair {
+    int roomHf;
+    int lpf;
+};
+
+class ReverbContext final : public EffectContext {
+  public:
+    ReverbContext(int statusDepth, const Parameter::Common& common,
+                  const lvm::ReverbEffectType& type)
+        : EffectContext(statusDepth, common), mType(type) {
+        LOG(DEBUG) << __func__ << type;
+        init();
+    }
+    ~ReverbContext() override {
+        LOG(DEBUG) << __func__;
+        deInit();
+    }
+
+    RetCode init();
+    void deInit();
+
+    RetCode enable();
+    RetCode disable();
+
+    bool isAuxiliary();
+    bool isPreset();
+
+    RetCode setPresetReverbPreset(const PresetReverb::Presets& preset);
+    PresetReverb::Presets getPresetReverbPreset() const { return mNextPreset; }
+
+    RetCode setEnvironmentalReverbRoomLevel(int roomLevel);
+    int getEnvironmentalReverbRoomLevel() const { return mRoomLevel; }
+    RetCode setEnvironmentalReverbRoomHfLevel(int roomHfLevel);
+    int getEnvironmentalReverbRoomHfLevel() const { return mRoomHfLevel; }
+    RetCode setEnvironmentalReverbDecayTime(int decayTime);
+    int getEnvironmentalReverbDecayTime() const { return mDecayTime; }
+    RetCode setEnvironmentalReverbDecayHfRatio(int decayHfRatio);
+    int getEnvironmentalReverbDecayHfRatio() const { return mDecayHfRatio; }
+    RetCode setEnvironmentalReverbLevel(int level);
+    int getEnvironmentalReverbLevel() const { return mLevel; }
+    RetCode setEnvironmentalReverbDelay(int delay);
+    int getEnvironmentalReverbDelay() const { return mDelay; }
+    RetCode setEnvironmentalReverbDiffusion(int diffusion);
+    int getEnvironmentalReverbDiffusion() const { return mDiffusion; }
+    RetCode setEnvironmentalReverbDensity(int density);
+    int getEnvironmentalReverbDensity() const { return mDensity; }
+    RetCode setEnvironmentalReverbBypass(bool bypass);
+    bool getEnvironmentalReverbBypass() const { return mBypass; }
+
+    RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) override;
+    Parameter::VolumeStereo getVolumeStereo() override { return mVolumeStereo; }
+
+    RetCode setReflectionsDelay(int delay) {
+        mReflectionsDelayMs = delay;
+        return RetCode::SUCCESS;
+    }
+    bool getReflectionsDelay() const { return mReflectionsDelayMs; }
+
+    RetCode setReflectionsLevel(int level) {
+        mReflectionsLevelMb = level;
+        return RetCode::SUCCESS;
+    }
+    bool getReflectionsLevel() const { return mReflectionsLevelMb; }
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    static constexpr inline float kUnitVolume = 1;
+    static constexpr inline float kSendLevel = 0.75f;
+    static constexpr inline int kDefaultLevel = 0;
+    static constexpr inline int kDefaultLPF = 23999;      /* Default low pass filter, in Hz */
+    static constexpr inline int kDefaultHPF = 50;         /* Default high pass filter, in Hz */
+    static constexpr inline int kDefaultDecayTime = 1490; /* Default Decay time, in ms */
+    static constexpr inline int kDefaultDensity = 100;    /* Default Echo density */
+    static constexpr inline int kDefaultDamping = 21;
+    static constexpr inline int kDefaultRoomSize = 100;
+
+    static inline const std::vector<LPFPair> kLPFMapping = {
+            // Limit range to 50 for LVREV parameter range
+            {-10000, 50}, {-5000, 50},  {-4000, 50},  {-3000, 158}, {-2000, 502}, {-1000, 1666},
+            {-900, 1897}, {-800, 2169}, {-700, 2496}, {-600, 2895}, {-500, 3400}, {-400, 4066},
+            {-300, 5011}, {-200, 6537}, {-100, 9826}, {-99, 9881},  {-98, 9937},  {-97, 9994},
+            {-96, 10052}, {-95, 10111}, {-94, 10171}, {-93, 10231}, {-92, 10293}, {-91, 10356},
+            {-90, 10419}, {-89, 10484}, {-88, 10549}, {-87, 10616}, {-86, 10684}, {-85, 10753},
+            {-84, 10823}, {-83, 10895}, {-82, 10968}, {-81, 11042}, {-80, 11117}, {-79, 11194},
+            {-78, 11272}, {-77, 11352}, {-76, 11433}, {-75, 11516}, {-74, 11600}, {-73, 11686},
+            {-72, 11774}, {-71, 11864}, {-70, 11955}, {-69, 12049}, {-68, 12144}, {-67, 12242},
+            {-66, 12341}, {-65, 12443}, {-64, 12548}, {-63, 12654}, {-62, 12763}, {-61, 12875},
+            {-60, 12990}, {-59, 13107}, {-58, 13227}, {-57, 13351}, {-56, 13477}, {-55, 13607},
+            {-54, 13741}, {-53, 13878}, {-52, 14019}, {-51, 14164}, {-50, 14313}, {-49, 14467},
+            {-48, 14626}, {-47, 14789}, {-46, 14958}, {-45, 15132}, {-44, 15312}, {-43, 15498},
+            {-42, 15691}, {-41, 15890}, {-40, 16097}, {-39, 16311}, {-38, 16534}, {-37, 16766},
+            {-36, 17007}, {-35, 17259}, {-34, 17521}, {-33, 17795}, {-32, 18081}, {-31, 18381},
+            {-30, 18696}, {-29, 19027}, {-28, 19375}, {-27, 19742}, {-26, 20129}, {-25, 20540},
+            {-24, 20976}, {-23, 21439}, {-22, 21934}, {-21, 22463}, {-20, 23031}, {-19, 23643},
+            {-18, 23999}};
+
+    static inline const std::vector<int> kLevelMapping = {
+            -12000, -4000, -3398, -3046, -2796, -2603, -2444, -2310, -2194, -2092, -2000, -1918,
+            -1842,  -1773, -1708, -1648, -1592, -1540, -1490, -1443, -1398, -1356, -1316, -1277,
+            -1240,  -1205, -1171, -1138, -1106, -1076, -1046, -1018, -990,  -963,  -938,  -912,
+            -888,   -864,  -841,  -818,  -796,  -775,  -754,  -734,  -714,  -694,  -675,  -656,
+            -638,   -620,  -603,  -585,  -568,  -552,  -536,  -520,  -504,  -489,  -474,  -459,
+            -444,   -430,  -416,  -402,  -388,  -375,  -361,  -348,  -335,  -323,  -310,  -298,
+            -286,   -274,  -262,  -250,  -239,  -228,  -216,  -205,  -194,  -184,  -173,  -162,
+            -152,   -142,  -132,  -121,  -112,  -102,  -92,   -82,   -73,   -64,   -54,   -45,
+            -36,    -27,   -18,   -9,    0};
+
+    static inline std::unordered_map<PresetReverb::Presets, t_reverb_settings> mReverbPresets = {
+            {PresetReverb::Presets::NONE, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
+            {PresetReverb::Presets::SMALLROOM,
+             {-400, -600, 1100, 830, -400, 5, 500, 10, 1000, 1000}},
+            {PresetReverb::Presets::MEDIUMROOM,
+             {-400, -600, 1300, 830, -1000, 20, -200, 20, 1000, 1000}},
+            {PresetReverb::Presets::LARGEROOM,
+             {-400, -600, 1500, 830, -1600, 5, -1000, 40, 1000, 1000}},
+            {PresetReverb::Presets::MEDIUMHALL,
+             {-400, -600, 1800, 700, -1300, 15, -800, 30, 1000, 1000}},
+            {PresetReverb::Presets::LARGEHALL,
+             {-400, -600, 1800, 700, -2000, 30, -1400, 60, 1000, 1000}},
+            {PresetReverb::Presets::PLATE, {-400, -200, 1300, 900, 0, 2, 0, 10, 1000, 750}}};
+
+    std::mutex mMutex;
+    const lvm::ReverbEffectType mType;
+    bool mEnabled = false;
+    LVREV_Handle_t mInstance GUARDED_BY(mMutex);
+
+    int mRoomLevel = 0;
+    int mRoomHfLevel = 0;
+    int mDecayTime = 0;
+    int mDecayHfRatio = 0;
+    int mLevel = 0;
+    int mDelay = 0;
+    int mDiffusion = 0;
+    int mDensity = 0;
+    bool mBypass = 0;
+    int mReflectionsLevelMb = 0;
+    int mReflectionsDelayMs = 0;
+
+    PresetReverb::Presets mPreset;
+    PresetReverb::Presets mNextPreset;
+
+    int mSamplesToExitCount;
+
+    Parameter::VolumeStereo mVolume;
+    Parameter::VolumeStereo mPrevVolume;
+    VolumeMode volumeMode;
+
+    void initControlParameter(LVREV_ControlParams_st& params);
+    int16_t convertHfLevel(int hfLevel);
+    int convertLevel(int level);
+    void loadPreset();
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
new file mode 100644
index 0000000..37f9287
--- /dev/null
+++ b/media/libeffects/lvm/wrapper/Reverb/aidl/ReverbTypes.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android/binder_enums.h>
+#include <audio_effects/effect_environmentalreverb.h>
+#include <audio_effects/effect_presetreverb.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "effect-impl/EffectTypes.h"
+// from Reverb/lib
+#include "LVREV.h"
+
+namespace aidl::android::hardware::audio::effect {
+namespace lvm {
+
+constexpr inline int kMaxCallSize = 256;
+constexpr inline int kMinLevel = -6000;
+constexpr inline int kMaxT60 = 7000; /* Maximum decay time */
+constexpr inline int kMaxReverbLevel = 2000;
+constexpr inline int kMaxFrameSize = 2560;
+constexpr inline int kCpuLoadARM9E = 470;                      // Expressed in 0.1 MIPS
+constexpr inline int kMemUsage = (71 + (kMaxFrameSize >> 7));  // Expressed in kB
+
+static const std::vector<Range::EnvironmentalReverbRange> kEnvReverbRanges = {
+        MAKE_RANGE(EnvironmentalReverb, roomLevelMb, lvm::kMinLevel, 0),
+        MAKE_RANGE(EnvironmentalReverb, roomHfLevelMb, -4000, 0),
+        MAKE_RANGE(EnvironmentalReverb, decayTimeMs, 0, lvm::kMaxT60),
+        MAKE_RANGE(EnvironmentalReverb, decayHfRatioPm, 100, 2000),
+        MAKE_RANGE(EnvironmentalReverb, levelMb, lvm::kMinLevel, 0),
+        MAKE_RANGE(EnvironmentalReverb, delayMs, 0, 65),
+        MAKE_RANGE(EnvironmentalReverb, diffusionPm, 0, 1000),
+        MAKE_RANGE(EnvironmentalReverb, densityPm, 0, 1000)};
+static const Capability kEnvReverbCap = {
+        .range = Range::make<Range::environmentalReverb>(kEnvReverbRanges)};
+
+// NXP SW auxiliary environmental reverb
+static const std::string kAuxEnvReverbEffectName = "Auxiliary Environmental Reverb";
+static const Descriptor kAuxEnvReverbDesc = {
+        .common = {.id = {.type = getEffectTypeUuidEnvReverb(),
+                          .uuid = getEffectImplUuidAuxEnvReverb(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::AUXILIARY},
+                   .cpuLoad = kCpuLoadARM9E,
+                   .memoryUsage = kMemUsage,
+                   .name = kAuxEnvReverbEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kEnvReverbCap};
+
+// NXP SW insert environmental reverb
+static const std::string kInsertEnvReverbEffectName = "Insert Environmental Reverb";
+static const Descriptor kInsertEnvReverbDesc = {
+        .common = {.id = {.type = getEffectTypeUuidEnvReverb(),
+                          .uuid = getEffectImplUuidInsertEnvReverb(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .cpuLoad = kCpuLoadARM9E,
+                   .memoryUsage = kMemUsage,
+                   .name = kInsertEnvReverbEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kEnvReverbCap};
+
+static const std::vector<PresetReverb::Presets> kSupportedPresets{
+        ndk::enum_range<PresetReverb::Presets>().begin(),
+        ndk::enum_range<PresetReverb::Presets>().end()};
+static const std::vector<Range::PresetReverbRange> kPresetReverbRanges = {
+        MAKE_RANGE(PresetReverb, supportedPresets, kSupportedPresets, kSupportedPresets)};
+static const Capability kPresetReverbCap = {
+        .range = Range::make<Range::presetReverb>(kPresetReverbRanges)};
+
+// NXP SW auxiliary preset reverb
+static const std::string kAuxPresetReverbEffectName = "Auxiliary Preset Reverb";
+static const Descriptor kAuxPresetReverbDesc = {
+        .common = {.id = {.type = getEffectTypeUuidPresetReverb(),
+                          .uuid = getEffectImplUuidAuxPresetReverb(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::AUXILIARY},
+                   .cpuLoad = kCpuLoadARM9E,
+                   .memoryUsage = kMemUsage,
+                   .name = kAuxPresetReverbEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kPresetReverbCap};
+
+// NXP SW insert preset reverb
+static const std::string kInsertPresetReverbEffectName = "Insert Preset Reverb";
+static const Descriptor kInsertPresetReverbDesc = {
+        .common = {.id = {.type = getEffectTypeUuidPresetReverb(),
+                          .uuid = getEffectImplUuidInsertPresetReverb(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::FIRST,
+                             .volume = Flags::Volume::CTRL},
+                   .cpuLoad = kCpuLoadARM9E,
+                   .memoryUsage = kMemUsage,
+                   .name = kInsertPresetReverbEffectName,
+                   .implementor = "NXP Software Ltd."},
+        .capability = kPresetReverbCap};
+
+enum class ReverbEffectType {
+    AUX_ENV,
+    INSERT_ENV,
+    AUX_PRESET,
+    INSERT_PRESET,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const ReverbEffectType& type) {
+    switch (type) {
+        case ReverbEffectType::AUX_ENV:
+            return out << kAuxEnvReverbEffectName;
+        case ReverbEffectType::INSERT_ENV:
+            return out << kInsertEnvReverbEffectName;
+        case ReverbEffectType::AUX_PRESET:
+            return out << kAuxPresetReverbEffectName;
+        case ReverbEffectType::INSERT_PRESET:
+            return out << kInsertPresetReverbEffectName;
+    }
+    return out << "EnumReverbEffectTypeError";
+}
+
+inline std::ostream& operator<<(std::ostream& out, const LVREV_ReturnStatus_en& status) {
+    switch (status) {
+        case LVREV_SUCCESS:
+            return out << "LVREV_SUCCESS";
+        case LVREV_NULLADDRESS:
+            return out << "LVREV_NULLADDRESS";
+        case LVREV_OUTOFRANGE:
+            return out << "LVREV_OUTOFRANGE";
+        case LVREV_INVALIDNUMSAMPLES:
+            return out << "LVREV_INVALIDNUMSAMPLES";
+        case LVREV_RETURNSTATUS_DUMMY:
+            return out << "LVREV_RETURNSTATUS_DUMMY";
+    }
+    return out << "EnumLvrevRetStatusError";
+}
+
+}  // namespace lvm
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index c6e036a..d018c47 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -58,3 +58,39 @@
         "libwebrtc_absl_headers",
     ],
 }
+
+cc_library_shared {
+    name: "libpreprocessingaidl",
+    srcs: [
+        "aidl/PreProcessingContext.cpp",
+        "aidl/EffectPreProcessing.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+    ],
+    local_include_dirs: ["aidl"],
+    shared_libs: [
+        "liblog",
+        "libutils",
+        "libaudioutils",
+    ],
+    static_libs: [
+        "webrtc_audio_processing",
+    ],
+    header_libs: [
+        "libwebrtc_absl_headers",
+        "libaudioeffects",
+        "libhardware_headers",
+    ],
+    cflags: [
+        "-Wthread-safety",
+        "-Wno-unused-parameter",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 61a2bf5..59f1fc3 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -102,7 +102,8 @@
     uint32_t state;                // current state (enum preproc_session_state)
     int id;                        // audio session ID
     int io;                        // handle of input stream this session is on
-    webrtc::AudioProcessing* apm;  // handle on webRTC audio processing module (APM)
+    rtc::scoped_refptr<webrtc::AudioProcessing>
+            apm;  // handle on webRTC audio processing module (APM)
     // Audio Processing module builder
     webrtc::AudioProcessingBuilder ap_builder;
     // frameCount represents the size of the buffers used for processing, and must represent 10ms.
@@ -260,9 +261,6 @@
     ALOGV("Agc2Init");
     effect->session->config = effect->session->apm->GetConfig();
     effect->session->config.gain_controller2.fixed_digital.gain_db = 0.f;
-    effect->session->config.gain_controller2.adaptive_digital.level_estimator =
-            effect->session->config.gain_controller2.kRms;
-    effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db = 2.f;
     effect->session->apm->ApplyConfig(effect->session->config);
     return 0;
 }
@@ -332,24 +330,19 @@
             ALOGV("Agc2GetParameter() target level %f dB", *(float*)pValue);
             break;
         case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
-            *(uint32_t*)pValue = (uint32_t)(
-                    effect->session->config.gain_controller2.adaptive_digital.level_estimator);
-            ALOGV("Agc2GetParameter() level estimator %d",
-                  *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+            // WebRTC only supports RMS level estimator now
+            *(uint32_t*)pValue = (uint32_t)(0);
+            ALOGV("Agc2GetParameter() level estimator RMS");
             break;
         case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
-            *(float*)pValue = (float)(effect->session->config.gain_controller2.adaptive_digital
-                                              .extra_saturation_margin_db);
+            *(float*)pValue = (float)(2.0);
             ALOGV("Agc2GetParameter() extra saturation margin %f dB", *(float*)pValue);
             break;
         case AGC2_PARAM_PROPERTIES:
             pProperties->fixedDigitalGain =
                     (float)(effect->session->config.gain_controller2.fixed_digital.gain_db);
-            pProperties->level_estimator = (uint32_t)(
-                    effect->session->config.gain_controller2.adaptive_digital.level_estimator);
-            pProperties->extraSaturationMargin =
-                    (float)(effect->session->config.gain_controller2.adaptive_digital
-                                    .extra_saturation_margin_db);
+            pProperties->level_estimator = 0;
+            pProperties->extraSaturationMargin = 2.0;
             break;
         default:
             ALOGW("Agc2GetParameter() unknown param %d", param);
@@ -438,16 +431,19 @@
             effect->session->config.gain_controller2.fixed_digital.gain_db = valueFloat;
             break;
         case AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR:
-            ALOGV("Agc2SetParameter() level estimator %d",
-                  *(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
-            effect->session->config.gain_controller2.adaptive_digital.level_estimator =
-                    (*(webrtc::AudioProcessing::Config::GainController2::LevelEstimator*)pValue);
+            ALOGV("Agc2SetParameter() level estimator %d", *(uint32_t*)pValue);
+            if (*(uint32_t*)pValue != 0) {
+              // only RMS is supported
+              status = -EINVAL;
+            }
             break;
         case AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN:
             valueFloat = (float)(*(int32_t*)pValue);
             ALOGV("Agc2SetParameter() extra saturation margin %f dB", valueFloat);
-            effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
-                    valueFloat;
+            if (valueFloat != 2.0) {
+              // extra_staturation_margin_db is no longer configurable in webrtc
+              status = -EINVAL;
+            }
             break;
         case AGC2_PARAM_PROPERTIES:
             ALOGV("Agc2SetParameter() properties gain %f, level %d margin %f",
@@ -455,11 +451,9 @@
                   pProperties->extraSaturationMargin);
             effect->session->config.gain_controller2.fixed_digital.gain_db =
                     pProperties->fixedDigitalGain;
-            effect->session->config.gain_controller2.adaptive_digital.level_estimator =
-                    (webrtc::AudioProcessing::Config::GainController2::LevelEstimator)
-                            pProperties->level_estimator;
-            effect->session->config.gain_controller2.adaptive_digital.extra_saturation_margin_db =
-                    pProperties->extraSaturationMargin;
+            if (pProperties->level_estimator != 0 || pProperties->extraSaturationMargin != 2.0) {
+              status = -EINVAL;
+            }
             break;
         default:
             ALOGW("Agc2SetParameter() unknown param %08x value %08x", param, *(uint32_t*)pValue);
@@ -879,8 +873,8 @@
 
 error:
     if (session->createdMsk == 0) {
-        delete session->apm;
-        session->apm = NULL;
+        // Scoped_refptr will handle reference counting here
+        session->apm = nullptr;
     }
     return status;
 }
@@ -889,8 +883,8 @@
     ALOGW_IF(Effect_Release(fx) != 0, " Effect_Release() failed for proc ID %d", fx->procId);
     session->createdMsk &= ~(1 << fx->procId);
     if (session->createdMsk == 0) {
-        delete session->apm;
-        session->apm = NULL;
+        // Scoped_refptr will handle reference counting here
+        session->apm = nullptr;
         session->id = 0;
     }
 
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
new file mode 100644
index 0000000..e8ae8b3
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.cpp
@@ -0,0 +1,456 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectPreProcessing"
+#include <algorithm>
+#include <unordered_set>
+
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "EffectPreProcessing.h"
+
+using aidl::android::hardware::audio::effect::getEffectImplUuidAcousticEchoCancelerSw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAutomaticGainControlV1Sw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidAutomaticGainControlV2Sw;
+using aidl::android::hardware::audio::effect::getEffectImplUuidNoiseSuppressionSw;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::EffectPreProcessing;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+bool isPreProcessingUuidSupported(const AudioUuid& uuid) {
+    return uuid == getEffectImplUuidAcousticEchoCancelerSw() ||
+           uuid == getEffectImplUuidAutomaticGainControlV1Sw() ||
+           uuid == getEffectImplUuidAutomaticGainControlV2Sw() ||
+           uuid == getEffectImplUuidNoiseSuppressionSw();
+}
+
+extern "C" binder_exception_t createEffect(const AudioUuid* uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!uuid || !isPreProcessingUuidSupported(*uuid)) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<EffectPreProcessing>(*uuid);
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || !isPreProcessingUuidSupported(*in_impl_uuid)) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (*in_impl_uuid == getEffectImplUuidAcousticEchoCancelerSw()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::kAcousticEchoCancelerDesc;
+    } else if (*in_impl_uuid == getEffectImplUuidAutomaticGainControlV1Sw()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::kAutomaticGainControlV1Desc;
+    } else if (*in_impl_uuid == getEffectImplUuidAutomaticGainControlV2Sw()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::kAutomaticGainControlV2Desc;
+    } else if (*in_impl_uuid == getEffectImplUuidNoiseSuppressionSw()) {
+        *_aidl_return = aidl::android::hardware::audio::effect::kNoiseSuppressionDesc;
+    }
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectPreProcessing::EffectPreProcessing(const AudioUuid& uuid) {
+    LOG(DEBUG) << __func__ << uuid.toString();
+    if (uuid == getEffectImplUuidAcousticEchoCancelerSw()) {
+        mType = PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION;
+        mDescriptor = &kAcousticEchoCancelerDesc;
+        mEffectName = &kAcousticEchoCancelerEffectName;
+    } else if (uuid == getEffectImplUuidAutomaticGainControlV1Sw()) {
+        mType = PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1;
+        mDescriptor = &kAutomaticGainControlV1Desc;
+        mEffectName = &kAutomaticGainControlV1EffectName;
+    } else if (uuid == getEffectImplUuidAutomaticGainControlV2Sw()) {
+        mType = PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2;
+        mDescriptor = &kAutomaticGainControlV2Desc;
+        mEffectName = &kAutomaticGainControlV2EffectName;
+    } else if (uuid == getEffectImplUuidNoiseSuppressionSw()) {
+        mType = PreProcessingEffectType::NOISE_SUPPRESSION;
+        mDescriptor = &kNoiseSuppressionDesc;
+        mEffectName = &kNoiseSuppressionEffectName;
+    } else {
+        LOG(ERROR) << __func__ << uuid.toString() << " not supported!";
+    }
+}
+
+EffectPreProcessing::~EffectPreProcessing() {
+    cleanUp();
+    LOG(DEBUG) << __func__;
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << _aidl_return->toString();
+    *_aidl_return = *mDescriptor;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterSpecific(const Parameter::Specific& specific) {
+    LOG(DEBUG) << __func__ << " specific " << specific.toString();
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto tag = specific.getTag();
+    switch (tag) {
+        case Parameter::Specific::acousticEchoCanceler:
+            return setParameterAcousticEchoCanceler(specific);
+        case Parameter::Specific::automaticGainControlV1:
+            return setParameterAutomaticGainControlV1(specific);
+        case Parameter::Specific::automaticGainControlV2:
+            return setParameterAutomaticGainControlV2(specific);
+        case Parameter::Specific::noiseSuppression:
+            return setParameterNoiseSuppression(specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "specificParamNotSupported");
+    }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAcousticEchoCanceler(
+        const Parameter::Specific& specific) {
+    auto& param = specific.get<Parameter::Specific::acousticEchoCanceler>();
+    RETURN_IF(!inRange(param, kAcousticEchoCancelerRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto tag = param.getTag();
+
+    switch (tag) {
+        case AcousticEchoCanceler::echoDelayUs: {
+            RETURN_IF(mContext->setAcousticEchoCancelerEchoDelay(
+                              param.get<AcousticEchoCanceler::echoDelayUs>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "echoDelayNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        case AcousticEchoCanceler::mobileMode: {
+            RETURN_IF(mContext->setAcousticEchoCancelerMobileMode(
+                              param.get<AcousticEchoCanceler::mobileMode>()) != RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "SettingMobileModeNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAutomaticGainControlV1(
+        const Parameter::Specific& specific) {
+    auto& param = specific.get<Parameter::Specific::automaticGainControlV1>();
+    RETURN_IF(!inRange(param, kAutomaticGainControlV1Ranges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto tag = param.getTag();
+
+    switch (tag) {
+        case AutomaticGainControlV1::targetPeakLevelDbFs: {
+            RETURN_IF(mContext->setAutomaticGainControlV1TargetPeakLevel(
+                              param.get<AutomaticGainControlV1::targetPeakLevelDbFs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "targetPeakLevelNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        case AutomaticGainControlV1::maxCompressionGainDb: {
+            RETURN_IF(mContext->setAutomaticGainControlV1MaxCompressionGain(
+                              param.get<AutomaticGainControlV1::maxCompressionGainDb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "maxCompressionGainNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        case AutomaticGainControlV1::enableLimiter: {
+            RETURN_IF(
+                    mContext->setAutomaticGainControlV1EnableLimiter(
+                            param.get<AutomaticGainControlV1::enableLimiter>()) != RetCode::SUCCESS,
+                    EX_ILLEGAL_ARGUMENT, "enableLimiterNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterAutomaticGainControlV2(
+        const Parameter::Specific& specific) {
+    auto& param = specific.get<Parameter::Specific::automaticGainControlV2>();
+    RETURN_IF(!inRange(param, kAutomaticGainControlV2Ranges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    auto tag = param.getTag();
+
+    switch (tag) {
+        case AutomaticGainControlV2::fixedDigitalGainMb: {
+            RETURN_IF(mContext->setAutomaticGainControlV2DigitalGain(
+                              param.get<AutomaticGainControlV2::fixedDigitalGainMb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "digitalGainNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        case AutomaticGainControlV2::levelEstimator: {
+            RETURN_IF(mContext->setAutomaticGainControlV2LevelEstimator(
+                              param.get<AutomaticGainControlV2::levelEstimator>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "levelEstimatorNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        case AutomaticGainControlV2::saturationMarginMb: {
+            RETURN_IF(mContext->setAutomaticGainControlV2SaturationMargin(
+                              param.get<AutomaticGainControlV2::saturationMarginMb>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "saturationMarginNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::setParameterNoiseSuppression(
+        const Parameter::Specific& specific) {
+    auto& param = specific.get<Parameter::Specific::noiseSuppression>();
+    auto tag = param.getTag();
+
+    switch (tag) {
+        case NoiseSuppression::level: {
+            RETURN_IF(mContext->setNoiseSuppressionLevel(param.get<NoiseSuppression::level>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "levelNotSupported");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterSpecific(const Parameter::Id& id,
+                                                             Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+
+    switch (tag) {
+        case Parameter::Id::acousticEchoCancelerTag:
+            return getParameterAcousticEchoCanceler(
+                    id.get<Parameter::Id::acousticEchoCancelerTag>(), specific);
+        case Parameter::Id::automaticGainControlV1Tag:
+            return getParameterAutomaticGainControlV1(
+                    id.get<Parameter::Id::automaticGainControlV1Tag>(), specific);
+        case Parameter::Id::automaticGainControlV2Tag:
+            return getParameterAutomaticGainControlV2(
+                    id.get<Parameter::Id::automaticGainControlV2Tag>(), specific);
+        case Parameter::Id::noiseSuppressionTag:
+            return getParameterNoiseSuppression(id.get<Parameter::Id::noiseSuppressionTag>(),
+                                                specific);
+        default:
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "wrongIdTag");
+    }
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAcousticEchoCanceler(
+        const AcousticEchoCanceler::Id& id, Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != AcousticEchoCanceler::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "AcousticEchoCancelerTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    AcousticEchoCanceler param;
+    auto tag = id.get<AcousticEchoCanceler::Id::commonTag>();
+    switch (tag) {
+        case AcousticEchoCanceler::echoDelayUs: {
+            param.set<AcousticEchoCanceler::echoDelayUs>(
+                    mContext->getAcousticEchoCancelerEchoDelay());
+            break;
+        }
+        case AcousticEchoCanceler::mobileMode: {
+            param.set<AcousticEchoCanceler::mobileMode>(
+                    mContext->getAcousticEchoCancelerMobileMode());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "AcousticEchoCancelerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::acousticEchoCanceler>(param);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAutomaticGainControlV1(
+        const AutomaticGainControlV1::Id& id, Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != AutomaticGainControlV1::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "AutomaticGainControlV1TagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    AutomaticGainControlV1 param;
+
+    auto tag = id.get<AutomaticGainControlV1::Id::commonTag>();
+    switch (tag) {
+        case AutomaticGainControlV1::targetPeakLevelDbFs: {
+            param.set<AutomaticGainControlV1::targetPeakLevelDbFs>(
+                    mContext->getAutomaticGainControlV1TargetPeakLevel());
+            break;
+        }
+        case AutomaticGainControlV1::maxCompressionGainDb: {
+            param.set<AutomaticGainControlV1::maxCompressionGainDb>(
+                    mContext->getAutomaticGainControlV1MaxCompressionGain());
+            break;
+        }
+        case AutomaticGainControlV1::enableLimiter: {
+            param.set<AutomaticGainControlV1::enableLimiter>(
+                    mContext->getAutomaticGainControlV1EnableLimiter());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV1TagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::automaticGainControlV1>(param);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterAutomaticGainControlV2(
+        const AutomaticGainControlV2::Id& id, Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != AutomaticGainControlV2::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "AutomaticGainControlV2TagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    AutomaticGainControlV2 param;
+
+    auto tag = id.get<AutomaticGainControlV2::Id::commonTag>();
+    switch (tag) {
+        case AutomaticGainControlV2::fixedDigitalGainMb: {
+            param.set<AutomaticGainControlV2::fixedDigitalGainMb>(
+                    mContext->getAutomaticGainControlV2DigitalGain());
+            break;
+        }
+        case AutomaticGainControlV2::levelEstimator: {
+            param.set<AutomaticGainControlV2::levelEstimator>(
+                    mContext->getAutomaticGainControlV2LevelEstimator());
+            break;
+        }
+        case AutomaticGainControlV2::saturationMarginMb: {
+            param.set<AutomaticGainControlV2::saturationMarginMb>(
+                    mContext->getAutomaticGainControlV2SaturationMargin());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "AutomaticGainControlV2TagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::automaticGainControlV2>(param);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectPreProcessing::getParameterNoiseSuppression(
+        const NoiseSuppression::Id& id, Parameter::Specific* specific) {
+    RETURN_IF(id.getTag() != NoiseSuppression::Id::commonTag, EX_ILLEGAL_ARGUMENT,
+              "NoiseSuppressionTagNotSupported");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+    NoiseSuppression param;
+
+    auto tag = id.get<NoiseSuppression::Id::commonTag>();
+    switch (tag) {
+        case NoiseSuppression::level: {
+            param.set<NoiseSuppression::level>(mContext->getNoiseSuppressionLevel());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "NoiseSuppressionTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::noiseSuppression>(param);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EffectPreProcessing::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+    } else {
+        // PreProcessingSession is a singleton
+        mContext = PreProcessingSession::getPreProcessingSession().createSession(
+                mType, 1 /* statusFmqDepth */, common);
+    }
+
+    return mContext;
+}
+
+std::shared_ptr<EffectContext> EffectPreProcessing::getContext() {
+    return mContext;
+}
+
+RetCode EffectPreProcessing::releaseContext() {
+    if (mContext) {
+        PreProcessingSession::getPreProcessingSession().releaseSession(mType,
+                                                                       mContext->getSessionId());
+        mContext.reset();
+    }
+    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};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->lvmProcess(in, out, sampleToProcess);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/EffectPreProcessing.h b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
new file mode 100644
index 0000000..fad848a
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/EffectPreProcessing.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "PreProcessingContext.h"
+#include "PreProcessingSession.h"
+#include "effect-impl/EffectImpl.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectPreProcessing final : public EffectImpl {
+  public:
+    explicit EffectPreProcessing(const AudioUuid& uuid);
+    ~EffectPreProcessing() override;
+
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    std::shared_ptr<EffectContext> getContext() override;
+    RetCode releaseContext() override;
+
+    IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+
+    std::string getEffectName() override { return *mEffectName; }
+
+  private:
+    std::shared_ptr<PreProcessingContext> mContext;
+    const Descriptor* mDescriptor;
+    const std::string* mEffectName;
+    PreProcessingEffectType mType;
+
+    ndk::ScopedAStatus setParameterAcousticEchoCanceler(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Id& id,
+                                                        Parameter::Specific* specific);
+
+    ndk::ScopedAStatus setParameterAutomaticGainControlV1(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Id& id,
+                                                          Parameter::Specific* specific);
+
+    ndk::ScopedAStatus setParameterAutomaticGainControlV2(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterAutomaticGainControlV2(const AutomaticGainControlV2::Id& id,
+                                                          Parameter::Specific* specific);
+
+    ndk::ScopedAStatus setParameterNoiseSuppression(const Parameter::Specific& specific);
+    ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Id& id,
+                                                    Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
new file mode 100644
index 0000000..c1e4eda
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstddef>
+#define LOG_TAG "PreProcessingContext"
+#include <Utils.h>
+
+#include "PreProcessingContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+using aidl::android::media::audio::common::AudioDeviceDescription;
+using aidl::android::media::audio::common::AudioDeviceType;
+
+RetCode PreProcessingContext::init(const Parameter::Common& common) {
+    std::lock_guard lg(mMutex);
+    webrtc::AudioProcessingBuilder apBuilder;
+    mAudioProcessingModule = apBuilder.Create();
+    if (mAudioProcessingModule == nullptr) {
+        LOG(ERROR) << "init could not get apm engine";
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+
+    updateConfigs(common);
+
+    mEnabledMsk = 0;
+    mProcessedMsk = 0;
+    mRevEnabledMsk = 0;
+    mRevProcessedMsk = 0;
+
+    auto config = mAudioProcessingModule->GetConfig();
+    switch (mType) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            config.echo_canceller.mobile_mode = true;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            config.gain_controller1.target_level_dbfs = kAgcDefaultTargetLevel;
+            config.gain_controller1.compression_gain_db = kAgcDefaultCompGain;
+            config.gain_controller1.enable_limiter = kAgcDefaultLimiter;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            config.gain_controller2.fixed_digital.gain_db = 0.f;
+            break;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            config.noise_suppression.level = kNsDefaultLevel;
+            break;
+    }
+    mAudioProcessingModule->ApplyConfig(config);
+    mState = PRE_PROC_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::deInit() {
+    std::lock_guard lg(mMutex);
+    mAudioProcessingModule = nullptr;
+    mState = PRE_PROC_STATE_UNINITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::enable() {
+    if (mState != PRE_PROC_STATE_INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    int typeMsk = (1 << int(mType));
+    std::lock_guard lg(mMutex);
+    // Check if effect is already enabled.
+    if ((mEnabledMsk & typeMsk) == typeMsk) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    mEnabledMsk |= typeMsk;
+    auto config = mAudioProcessingModule->GetConfig();
+    switch (mType) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            config.echo_canceller.enabled = true;
+            // AEC has reverse stream
+            mRevEnabledMsk |= typeMsk;
+            mRevProcessedMsk = 0;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            config.gain_controller1.enabled = true;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            config.gain_controller2.enabled = true;
+            break;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            config.noise_suppression.enabled = true;
+            break;
+    }
+    mProcessedMsk = 0;
+    mAudioProcessingModule->ApplyConfig(config);
+    mState = PRE_PROC_STATE_ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::disable() {
+    if (mState != PRE_PROC_STATE_ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    int typeMsk = (1 << int(mType));
+    std::lock_guard lg(mMutex);
+    // Check if effect is already disabled.
+    if ((mEnabledMsk & typeMsk) != typeMsk) {
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+    mEnabledMsk &= ~typeMsk;
+    auto config = mAudioProcessingModule->GetConfig();
+    switch (mType) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            config.echo_canceller.enabled = false;
+            // AEC has reverse stream
+            mRevEnabledMsk &= ~typeMsk;
+            mRevProcessedMsk = 0;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            config.gain_controller1.enabled = false;
+            break;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            config.gain_controller2.enabled = false;
+            break;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            config.noise_suppression.enabled = false;
+            break;
+    }
+    mProcessedMsk = 0;
+    mAudioProcessingModule->ApplyConfig(config);
+    mState = PRE_PROC_STATE_INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+RetCode PreProcessingContext::setCommon(const Parameter::Common& common) {
+    mCommon = common;
+    updateConfigs(common);
+    return RetCode::SUCCESS;
+}
+
+void PreProcessingContext::updateConfigs(const Parameter::Common& common) {
+    mInputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+    mInputConfig.set_num_channels(::aidl::android::hardware::audio::common::getChannelCount(
+                    common.input.base.channelMask));
+    mOutputConfig.set_sample_rate_hz(common.input.base.sampleRate);
+    mOutputConfig.set_num_channels(::aidl::android::hardware::audio::common::getChannelCount(
+                    common.output.base.channelMask));
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerEchoDelay(int echoDelayUs) {
+    mEchoDelayUs = echoDelayUs;
+    std::lock_guard lg(mMutex);
+    mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAcousticEchoCancelerEchoDelay() const {
+    return mEchoDelayUs;
+}
+
+RetCode PreProcessingContext::setAcousticEchoCancelerMobileMode(bool mobileMode) {
+    mMobileMode = mobileMode;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.echo_canceller.mobile_mode = mobileMode;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAcousticEchoCancelerMobileMode() const {
+    return mMobileMode;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel) {
+    mTargetPeakLevel = targetPeakLevel;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller1.target_level_dbfs = -(mTargetPeakLevel / 100);
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1TargetPeakLevel() const {
+    return mTargetPeakLevel;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain) {
+    mMaxCompressionGain = maxCompressionGain;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller1.compression_gain_db = mMaxCompressionGain / 100;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV1MaxCompressionGain() const {
+    return mMaxCompressionGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV1EnableLimiter(bool enableLimiter) {
+    mEnableLimiter = enableLimiter;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller1.enable_limiter = mEnableLimiter;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+bool PreProcessingContext::getAutomaticGainControlV1EnableLimiter() const {
+    return mEnableLimiter;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2DigitalGain(int gain) {
+    mDigitalGain = gain;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.gain_controller2.fixed_digital.gain_db = mDigitalGain;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2DigitalGain() const {
+    return mDigitalGain;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2LevelEstimator(
+        AutomaticGainControlV2::LevelEstimator levelEstimator) {
+    mLevelEstimator = levelEstimator;
+    return RetCode::SUCCESS;
+}
+
+AutomaticGainControlV2::LevelEstimator
+PreProcessingContext::getAutomaticGainControlV2LevelEstimator() const {
+    return mLevelEstimator;
+}
+
+RetCode PreProcessingContext::setAutomaticGainControlV2SaturationMargin(int saturationMargin) {
+    mSaturationMargin = saturationMargin;
+    return RetCode::SUCCESS;
+}
+
+int PreProcessingContext::getAutomaticGainControlV2SaturationMargin() const {
+    return mSaturationMargin;
+}
+
+RetCode PreProcessingContext::setNoiseSuppressionLevel(NoiseSuppression::Level level) {
+    mLevel = level;
+    std::lock_guard lg(mMutex);
+    auto config = mAudioProcessingModule->GetConfig();
+    config.noise_suppression.level =
+            (webrtc::AudioProcessing::Config::NoiseSuppression::Level)level;
+    mAudioProcessingModule->ApplyConfig(config);
+    return RetCode::SUCCESS;
+}
+
+NoiseSuppression::Level PreProcessingContext::getNoiseSuppressionLevel() const {
+    return mLevel;
+}
+
+IEffect::Status PreProcessingContext::lvmProcess(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!in, status, "nullInput");
+    RETURN_VALUE_IF(!out, status, "nullOutput");
+    status = {EX_ILLEGAL_STATE, 0, 0};
+    int64_t inputFrameCount = getCommon().input.frameCount;
+    int64_t outputFrameCount = getCommon().output.frameCount;
+    RETURN_VALUE_IF(inputFrameCount != outputFrameCount, status, "FrameCountMismatch");
+    RETURN_VALUE_IF(0 == getInputFrameSize(), status, "zeroFrameSize");
+
+    LOG(DEBUG) << __func__ << " start processing";
+    std::lock_guard lg(mMutex);
+
+    mProcessedMsk |= (1 << int(mType));
+
+    // webrtc implementation clear out was_stream_delay_set every time after ProcessStream() call
+    mAudioProcessingModule->set_stream_delay_ms(mEchoDelayUs / 1000);
+
+    if ((mProcessedMsk & mEnabledMsk) == mEnabledMsk) {
+        mProcessedMsk = 0;
+        int processStatus = mAudioProcessingModule->ProcessStream(
+                (const int16_t* const)in, mInputConfig, mOutputConfig, (int16_t* const)out);
+        if (processStatus != 0) {
+            LOG(ERROR) << "Process stream failed with error " << processStatus;
+            return status;
+        }
+    }
+
+    mRevProcessedMsk |= (1 << int(mType));
+
+    if ((mRevProcessedMsk & mRevEnabledMsk) == mRevEnabledMsk) {
+        mRevProcessedMsk = 0;
+        int revProcessStatus = mAudioProcessingModule->ProcessReverseStream(
+                (const int16_t* const)in, mInputConfig, mInputConfig, (int16_t* const)out);
+        if (revProcessStatus != 0) {
+            LOG(ERROR) << "Process reverse stream failed with error " << revProcessStatus;
+            return status;
+        }
+    }
+
+    return {STATUS_OK, samples, samples};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingContext.h b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
new file mode 100644
index 0000000..9ba1bbe
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingContext.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+#include <audio_processing.h>
+#include <unordered_map>
+
+#include "PreProcessingTypes.h"
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+enum PreProcEffectState {
+    PRE_PROC_STATE_UNINITIALIZED,
+    PRE_PROC_STATE_INITIALIZED,
+    PRE_PROC_STATE_ACTIVE,
+};
+
+class PreProcessingContext final : public EffectContext {
+  public:
+    PreProcessingContext(int statusDepth, const Parameter::Common& common,
+                         const PreProcessingEffectType& type)
+        : EffectContext(statusDepth, common), mType(type) {
+        LOG(DEBUG) << __func__ << type;
+        mState = PRE_PROC_STATE_UNINITIALIZED;
+    }
+    ~PreProcessingContext() override { LOG(DEBUG) << __func__; }
+
+    RetCode init(const Parameter::Common& common);
+    RetCode deInit();
+
+    PreProcessingEffectType getPreProcessingType() const { return mType; }
+
+    RetCode enable();
+    RetCode disable();
+
+    RetCode setCommon(const Parameter::Common& common) override;
+    void updateConfigs(const Parameter::Common& common);
+
+    RetCode setAcousticEchoCancelerEchoDelay(int echoDelayUs);
+    int getAcousticEchoCancelerEchoDelay() const;
+    RetCode setAcousticEchoCancelerMobileMode(bool mobileMode);
+    bool getAcousticEchoCancelerMobileMode() const;
+
+    RetCode setAutomaticGainControlV1TargetPeakLevel(int targetPeakLevel);
+    int getAutomaticGainControlV1TargetPeakLevel() const;
+    RetCode setAutomaticGainControlV1MaxCompressionGain(int maxCompressionGain);
+    int getAutomaticGainControlV1MaxCompressionGain() const;
+    RetCode setAutomaticGainControlV1EnableLimiter(bool enableLimiter);
+    bool getAutomaticGainControlV1EnableLimiter() const;
+
+    RetCode setAutomaticGainControlV2DigitalGain(int gain);
+    int getAutomaticGainControlV2DigitalGain() const;
+    RetCode setAutomaticGainControlV2LevelEstimator(
+            AutomaticGainControlV2::LevelEstimator levelEstimator);
+    AutomaticGainControlV2::LevelEstimator getAutomaticGainControlV2LevelEstimator() const;
+    RetCode setAutomaticGainControlV2SaturationMargin(int saturationMargin);
+    int getAutomaticGainControlV2SaturationMargin() const;
+
+    RetCode setNoiseSuppressionLevel(NoiseSuppression::Level level);
+    NoiseSuppression::Level getNoiseSuppressionLevel() const;
+
+    IEffect::Status lvmProcess(float* in, float* out, int samples);
+
+  private:
+    static constexpr inline int kAgcDefaultTargetLevel = 3;
+    static constexpr inline int kAgcDefaultCompGain = 9;
+    static constexpr inline bool kAgcDefaultLimiter = true;
+    static constexpr inline webrtc::AudioProcessing::Config::NoiseSuppression::Level
+            kNsDefaultLevel = webrtc::AudioProcessing::Config::NoiseSuppression::kModerate;
+
+    std::mutex mMutex;
+    const PreProcessingEffectType mType;
+    PreProcEffectState mState;  // current state
+
+    // handle on webRTC audio processing module (APM)
+    rtc::scoped_refptr<webrtc::AudioProcessing> mAudioProcessingModule GUARDED_BY(mMutex);
+
+    int mEnabledMsk GUARDED_BY(mMutex);       // bit field containing IDs of enabled pre processors
+    int mProcessedMsk GUARDED_BY(mMutex);     // bit field containing IDs of pre processors already
+                                              // processed in current round
+    int mRevEnabledMsk GUARDED_BY(mMutex);    // bit field containing IDs of enabled pre processors
+                                              // with reverse channel
+    int mRevProcessedMsk GUARDED_BY(mMutex);  // bit field containing IDs of pre processors with
+                                              // reverse channel already processed in current round
+
+    webrtc::StreamConfig mInputConfig;   // input stream configuration
+    webrtc::StreamConfig mOutputConfig;  // output stream configuration
+
+    // Acoustic Echo Canceler
+    int mEchoDelayUs = 0;
+    bool mMobileMode = false;
+
+    // Automatic Gain Control V1
+    int mTargetPeakLevel = 0;
+    int mMaxCompressionGain = 0;
+    bool mEnableLimiter = false;
+
+    // Automatic Gain Control V2
+    int mDigitalGain = 0;
+    AutomaticGainControlV2::LevelEstimator mLevelEstimator =
+            AutomaticGainControlV2::LevelEstimator::RMS;
+    int mSaturationMargin = 2;
+
+    // NoiseSuppression
+    NoiseSuppression::Level mLevel = NoiseSuppression::Level::LOW;
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingSession.h b/media/libeffects/preprocessing/aidl/PreProcessingSession.h
new file mode 100644
index 0000000..877292f
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingSession.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <memory>
+#include <unordered_map>
+
+#include <android-base/logging.h>
+#include <android-base/thread_annotations.h>
+
+#include "PreProcessingContext.h"
+#include "PreProcessingTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * @brief Maintain all effect pre-processing sessions.
+ *
+ * Sessions are identified with the session ID, maximum of MAX_BUNDLE_SESSIONS is supported by the
+ * pre-processing implementation.
+ */
+class PreProcessingSession {
+  public:
+    static PreProcessingSession& getPreProcessingSession() {
+        static PreProcessingSession instance;
+        return instance;
+    }
+
+    static bool findPreProcessingTypeInList(
+            std::vector<std::shared_ptr<PreProcessingContext>>& list,
+            const PreProcessingEffectType& type, bool remove = false) {
+        auto itor = std::find_if(list.begin(), list.end(),
+                                 [type](const std::shared_ptr<PreProcessingContext>& bundle) {
+                                     return bundle->getPreProcessingType() == type;
+                                 });
+        if (itor == list.end()) {
+            return false;
+        }
+        if (remove) {
+            (*itor)->deInit();
+            list.erase(itor);
+        }
+        return true;
+    }
+
+    /**
+     * Create a certain type of PreProcessingContext in shared_ptr container, each session must not
+     * have more than one session for each type.
+     */
+    std::shared_ptr<PreProcessingContext> createSession(const PreProcessingEffectType& type,
+                                                        int statusDepth,
+                                                        const Parameter::Common& common) {
+        int sessionId = common.session;
+        LOG(DEBUG) << __func__ << type << " with sessionId " << sessionId;
+        std::lock_guard lg(mMutex);
+        if (mSessionMap.count(sessionId) == 0 && mSessionMap.size() >= MAX_PRE_PROC_SESSIONS) {
+            LOG(ERROR) << __func__ << " exceed max bundle session";
+            return nullptr;
+        }
+
+        if (mSessionMap.count(sessionId)) {
+            if (findPreProcessingTypeInList(mSessionMap[sessionId], type)) {
+                LOG(ERROR) << __func__ << type << " already exist in session " << sessionId;
+                return nullptr;
+            }
+        }
+
+        auto& list = mSessionMap[sessionId];
+        auto context = std::make_shared<PreProcessingContext>(statusDepth, common, type);
+        RETURN_VALUE_IF(!context, nullptr, "failedToCreateContext");
+
+        RetCode ret = context->init(common);
+        if (RetCode::SUCCESS != ret) {
+            LOG(ERROR) << __func__ << " context init ret " << ret;
+            return nullptr;
+        }
+        list.push_back(context);
+        return context;
+    }
+
+    void releaseSession(const PreProcessingEffectType& type, int sessionId) {
+        LOG(DEBUG) << __func__ << type << " sessionId " << sessionId;
+        std::lock_guard lg(mMutex);
+        if (mSessionMap.count(sessionId)) {
+            auto& list = mSessionMap[sessionId];
+            if (!findPreProcessingTypeInList(list, type, true /* remove */)) {
+                LOG(ERROR) << __func__ << " can't find " << type << "in session " << sessionId;
+                return;
+            }
+            if (list.empty()) {
+                mSessionMap.erase(sessionId);
+            }
+        }
+    }
+
+  private:
+    // Lock for mSessionMap access.
+    std::mutex mMutex;
+    // Max session number supported.
+    static constexpr int MAX_PRE_PROC_SESSIONS = 8;
+    std::unordered_map<int /* session ID */, std::vector<std::shared_ptr<PreProcessingContext>>>
+            mSessionMap GUARDED_BY(mMutex);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/aidl/PreProcessingTypes.h b/media/libeffects/preprocessing/aidl/PreProcessingTypes.h
new file mode 100644
index 0000000..4c2b8ba
--- /dev/null
+++ b/media/libeffects/preprocessing/aidl/PreProcessingTypes.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <optional>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include <audio_effects/effect_aec.h>
+#include <audio_effects/effect_agc.h>
+#include <audio_effects/effect_agc2.h>
+#include <audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "effect-impl/EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+// Acoustic Echo Cancellation
+static const std::string kAcousticEchoCancelerEffectName = "Acoustic Echo Canceler";
+static const std::vector<Range::AcousticEchoCancelerRange> kAcousticEchoCancelerRanges = {
+        MAKE_RANGE(AcousticEchoCanceler, AcousticEchoCanceler::echoDelayUs, 0, 500)};
+static const Capability kAcousticEchoCancelerCap = {.range = kAcousticEchoCancelerRanges};
+static const Descriptor kAcousticEchoCancelerDesc = {
+        .common = {.id = {.type = getEffectTypeUuidAcousticEchoCanceler(),
+                          .uuid = getEffectImplUuidAcousticEchoCancelerSw(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+                   .name = kAcousticEchoCancelerEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = kAcousticEchoCancelerCap};
+
+// Automatic Gain Control 1
+static const std::string kAutomaticGainControlV1EffectName = "Automatic Gain Control V1";
+static const std::vector<Range::AutomaticGainControlV1Range> kAutomaticGainControlV1Ranges = {
+        MAKE_RANGE(AutomaticGainControlV1, AutomaticGainControlV1::targetPeakLevelDbFs, -3100, 0),
+        MAKE_RANGE(AutomaticGainControlV1, AutomaticGainControlV1::maxCompressionGainDb, 0, 9000)};
+static const Capability kAutomaticGainControlV1Cap = {.range = kAutomaticGainControlV1Ranges};
+static const Descriptor kAutomaticGainControlV1Desc = {
+        .common = {.id = {.type = getEffectTypeUuidAutomaticGainControlV1(),
+                          .uuid = getEffectImplUuidAutomaticGainControlV1Sw(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+                   .name = kAutomaticGainControlV1EffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = kAutomaticGainControlV1Cap};
+
+// Automatic Gain Control 2
+static const std::string kAutomaticGainControlV2EffectName = "Automatic Gain Control V2";
+const std::vector<Range::AutomaticGainControlV2Range> kAutomaticGainControlV2Ranges = {
+        MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::fixedDigitalGainMb, 0, 90),
+        // extra_staturation_margin_db is no longer configurable in webrtc
+        MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::saturationMarginMb, 2, 2),
+        // WebRTC only supports RMS level estimator now
+        MAKE_RANGE(AutomaticGainControlV2, AutomaticGainControlV2::levelEstimator,
+                   AutomaticGainControlV2::LevelEstimator::RMS,
+                   AutomaticGainControlV2::LevelEstimator::RMS)};
+static const Capability kAutomaticGainControlV2Cap = {.range = kAutomaticGainControlV2Ranges};
+static const Descriptor kAutomaticGainControlV2Desc = {
+        .common = {.id = {.type = getEffectTypeUuidAutomaticGainControlV2(),
+                          .uuid = getEffectImplUuidAutomaticGainControlV2Sw(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+                   .name = kAutomaticGainControlV2EffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = kAutomaticGainControlV2Cap};
+
+// Noise suppression
+static const std::string kNoiseSuppressionEffectName = "Noise Suppression";
+static const Descriptor kNoiseSuppressionDesc = {
+        .common = {.id = {.type = getEffectTypeUuidNoiseSuppression(),
+                          .uuid = getEffectImplUuidNoiseSuppressionSw(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::PRE_PROC, .deviceIndication = true},
+                   .name = kNoiseSuppressionEffectName,
+                   .implementor = "The Android Open Source Project"}};
+
+enum class PreProcessingEffectType {
+    ACOUSTIC_ECHO_CANCELLATION,
+    AUTOMATIC_GAIN_CONTROL_V1,
+    AUTOMATIC_GAIN_CONTROL_V2,
+    NOISE_SUPPRESSION,
+};
+
+inline std::ostream& operator<<(std::ostream& out, const PreProcessingEffectType& type) {
+    switch (type) {
+        case PreProcessingEffectType::ACOUSTIC_ECHO_CANCELLATION:
+            return out << kAcousticEchoCancelerEffectName;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V1:
+            return out << kAutomaticGainControlV1EffectName;
+        case PreProcessingEffectType::AUTOMATIC_GAIN_CONTROL_V2:
+            return out << kAutomaticGainControlV2EffectName;
+        case PreProcessingEffectType::NOISE_SUPPRESSION:
+            return out << kNoiseSuppressionEffectName;
+    }
+    return out << "EnumPreProcessingEffectTypeError";
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
index 07006a1..8fdb864 100644
--- a/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/EffectPreprocessingTest.cpp
@@ -143,10 +143,6 @@
         const AGC2Params* agc2Params = &params->agc2Params;
         ASSERT_NO_FATAL_FAILURE(
                 effect.setParam(AGC2_PARAM_FIXED_DIGITAL_GAIN, agc2Params->fixedDigitalGain));
-        ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
-                                                agc2Params->adaptDigiLevelEstimator));
-        ASSERT_NO_FATAL_FAILURE(effect.setParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
-                                                agc2Params->extraSaturationMargin));
     } else if (isAECEffect(uuid)) {
         const AECParams* aecParams = &params->aecParams;
         ASSERT_NO_FATAL_FAILURE(effect.setParam(AEC_PARAM_ECHO_DELAY, aecParams->echoDelay));
diff --git a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
index 3bd93f8..03400d7 100644
--- a/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
+++ b/media/libeffects/preprocessing/tests/PreProcessingTest.cpp
@@ -400,20 +400,6 @@
             ALOGE("Invalid AGC2 Fixed Digital Gain. Error %d\n", status);
             return EXIT_FAILURE;
         }
-        if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_LEVEL_ESTIMATOR,
-                                               (uint32_t)preProcCfgParams.agc2Level,
-                                               effectHandle[PREPROC_AGC2]);
-            status != 0) {
-            ALOGE("Invalid AGC2 Level Estimator. Error %d\n", status);
-            return EXIT_FAILURE;
-        }
-        if (int status = preProcSetConfigParam(AGC2_PARAM_ADAPT_DIGI_EXTRA_SATURATION_MARGIN,
-                                               (float)preProcCfgParams.agc2SaturationMargin,
-                                               effectHandle[PREPROC_AGC2]);
-            status != 0) {
-            ALOGE("Invalid AGC2 Saturation Margin. Error %d\n", status);
-            return EXIT_FAILURE;
-        }
     }
     if (effectEn[PREPROC_NS]) {
         if (int status = preProcSetConfigParam(NS_PARAM_LEVEL, (uint32_t)preProcCfgParams.nsLevel,
diff --git a/media/libeffects/spatializer/benchmarks/Android.bp b/media/libeffects/spatializer/benchmarks/Android.bp
new file mode 100644
index 0000000..ab7e468
--- /dev/null
+++ b/media/libeffects/spatializer/benchmarks/Android.bp
@@ -0,0 +1,21 @@
+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"],
+}
+
+cc_benchmark {
+    name: "spatializer_benchmark",
+    vendor: true,
+    srcs: ["spatializer_benchmark.cpp"],
+    shared_libs: [
+        "libaudioutils",
+        "liblog",
+    ],
+    header_libs: [
+        "libhardware_headers",
+    ],
+}
diff --git a/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
new file mode 100644
index 0000000..e8ac480
--- /dev/null
+++ b/media/libeffects/spatializer/benchmarks/spatializer_benchmark.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <dlfcn.h>
+#include <random>
+#include <vector>
+
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <log/log.h>
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = [] {
+    audio_effect_library_t symbol{};
+    void* effectLib = dlopen("libspatialaudio.so", RTLD_NOW);
+    if (effectLib) {
+        audio_effect_library_t* effectInterface =
+                (audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+        if (effectInterface == nullptr) {
+            ALOGE("dlsym failed: %s", dlerror());
+            exit(-1);
+        }
+        symbol = (audio_effect_library_t)(*effectInterface);
+    } else {
+        ALOGE("dlopen failed: %s", dlerror());
+        exit(-1);
+    }
+    return symbol;
+}();
+
+// channel masks
+constexpr int kInputChMask = AUDIO_CHANNEL_OUT_5POINT1;
+
+// sampleRates
+constexpr size_t kSampleRates[] = {
+        44100,
+        48000,
+        96000,
+};
+constexpr size_t kNumSampleRates = std::size(kSampleRates);
+
+// duration in ms
+constexpr size_t kDurations[] = {2, 5, 10};
+constexpr size_t kNumDurations = std::size(kDurations);
+
+// effect uuids
+constexpr effect_uuid_t kEffectUuid = {
+        0xcc4677de, 0xff72, 0x11eb, 0x9a03, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03}};
+
+constexpr float kMinAmplitude = -1.0f;
+constexpr float kMaxAmplitude = 1.0f;
+
+/*******************************************************************
+ * A test result running on Pixel 5 for comparison.
+ * The first parameter indicates the sample rate.
+ * 0: 44100, 1: 48000, 2: 96000
+ * The second parameter indicates the duration in ms.
+ * 0: 2, 1: 5, 2: 10
+ * -------------------------------------------------------------
+ * Benchmark                   Time             CPU   Iterations
+ * -------------------------------------------------------------
+ * BM_SPATIALIZER/0/0     739848 ns       738497 ns          934
+ * BM_SPATIALIZER/0/1    1250503 ns      1248337 ns          480
+ * BM_SPATIALIZER/0/2    2094092 ns      2090092 ns          310
+ * BM_SPATIALIZER/1/0     783114 ns       781626 ns          683
+ * BM_SPATIALIZER/1/1    1332951 ns      1330473 ns          452
+ * BM_SPATIALIZER/1/2    2258313 ns      2254022 ns          289
+ * BM_SPATIALIZER/2/0    1210332 ns      1207957 ns          477
+ * BM_SPATIALIZER/2/1    2356259 ns      2351764 ns          269
+ * BM_SPATIALIZER/2/2    4267814 ns      4259567 ns          155
+ *******************************************************************/
+
+static void BM_SPATIALIZER(benchmark::State& state) {
+    const size_t sampleRate = kSampleRates[state.range(0)];
+    const size_t durationMs = kDurations[state.range(1)];
+    const size_t frameCount = durationMs * sampleRate / 1000;
+    const size_t inputChannelCount = audio_channel_count_from_out_mask(kInputChMask);
+    const size_t outputChannelCount = audio_channel_count_from_out_mask(AUDIO_CHANNEL_OUT_STEREO);
+
+    // Initialize input buffer with deterministic pseudo-random values
+    std::minstd_rand gen(kInputChMask);
+    std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
+    std::vector<float> input(frameCount * inputChannelCount);
+    for (auto& in : input) {
+        in = dis(gen);
+    }
+
+    effect_handle_t effectHandle = nullptr;
+    if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&kEffectUuid, 1 /* sessionId */,
+                                                                 1 /* ioId */, &effectHandle);
+        status != 0) {
+        ALOGE("create_effect returned an error = %d\n", status);
+        return;
+    }
+
+    effect_config_t config{};
+    config.inputCfg.samplingRate = config.outputCfg.samplingRate = sampleRate;
+    config.inputCfg.channels = kInputChMask;
+    config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+    config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+
+    int reply = 0;
+    uint32_t replySize = sizeof(reply);
+    if (int status = (*effectHandle)
+                             ->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+                                       &config, &replySize, &reply);
+        status != 0) {
+        ALOGE("command returned an error = %d\n", status);
+        return;
+    }
+
+    if (int status = (*effectHandle)
+                             ->command(effectHandle, EFFECT_CMD_ENABLE, sizeof(effect_config_t),
+                                       &config, &replySize, &reply);
+        status != 0) {
+        ALOGE("command returned an error = %d\n", status);
+        return;
+    }
+
+    // Run the test
+    std::vector<float> output(frameCount * outputChannelCount);
+    for (auto _ : state) {
+        benchmark::DoNotOptimize(input.data());
+        benchmark::DoNotOptimize(output.data());
+
+        audio_buffer_t inBuffer = {.frameCount = frameCount, .f32 = input.data()};
+        audio_buffer_t outBuffer = {.frameCount = frameCount, .f32 = output.data()};
+        (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+        benchmark::ClobberMemory();
+    }
+
+    state.SetComplexityN(frameCount);
+
+    if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
+        ALOGE("release_effect returned an error = %d\n", status);
+        return;
+    }
+}
+
+static void SPATIALIZERArgs(benchmark::internal::Benchmark* b) {
+    for (int i = 0; i < kNumSampleRates; i++) {
+        for (int j = 0; j < kNumDurations; ++j) {
+            b->Args({i, j});
+        }
+    }
+}
+
+BENCHMARK(BM_SPATIALIZER)->Apply(SPATIALIZERArgs);
+
+BENCHMARK_MAIN();
diff --git a/media/libeffects/spatializer/tests/Android.bp b/media/libeffects/spatializer/tests/Android.bp
new file mode 100644
index 0000000..704e873
--- /dev/null
+++ b/media/libeffects/spatializer/tests/Android.bp
@@ -0,0 +1,21 @@
+// Build the unit tests for spatializer effect
+
+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"],
+}
+
+cc_test {
+    name: "SpatializerTest",
+    defaults: [
+      "libeffects-test-defaults",
+    ],
+    host_supported: false,
+    srcs: [
+        "SpatializerTest.cpp",
+    ],
+}
diff --git a/media/libeffects/spatializer/tests/SpatializerTest.cpp b/media/libeffects/spatializer/tests/SpatializerTest.cpp
new file mode 100644
index 0000000..110fbb1
--- /dev/null
+++ b/media/libeffects/spatializer/tests/SpatializerTest.cpp
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SpatializerTest"
+
+#include <system/audio_effects/effect_spatializer.h>
+#include "EffectTestHelper.h"
+
+using namespace android;
+
+// relying on dlsym to fill the interface context
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = [] {
+    audio_effect_library_t symbol{};
+    void* effectLib = dlopen("libspatialaudio.so", RTLD_NOW);
+    if (effectLib) {
+        audio_effect_library_t* effectInterface =
+                (audio_effect_library_t*)dlsym(effectLib, AUDIO_EFFECT_LIBRARY_INFO_SYM_AS_STR);
+        if (effectInterface == nullptr) {
+            ALOGE("dlsym failed: %s", dlerror());
+            exit(-1);
+        }
+        symbol = (audio_effect_library_t)(*effectInterface);
+    } else {
+        ALOGE("dlopen failed: %s", dlerror());
+        exit(-1);
+    }
+    return symbol;
+}();
+
+// channel masks
+constexpr audio_channel_mask_t kSpatializerChMasks[] = {
+        AUDIO_CHANNEL_OUT_5POINT1,
+};
+constexpr size_t kNumSpatializerChMasks = std::size(kSpatializerChMasks);
+
+// sampleRates
+// TODO(b/234170025): Add all sampling rates once they are handled by spatializer
+constexpr int kSpatializerSampleRates[] = {44100, 48000, 96000};
+constexpr size_t kNumSpatializerSampleRates = std::size(kSpatializerSampleRates);
+
+// frame counts
+// TODO(b/234620538): Add sizes smaller than 80 once they are handled by spatializer
+constexpr size_t kSpatializerFrameCounts[] = {4800, 1920, 480, 80};
+constexpr size_t kNumSpatializerFrameCounts = std::size(kSpatializerFrameCounts);
+
+// effect uuids
+constexpr effect_uuid_t kSpatializerEffectUuids[] = {
+        {0xcc4677de, 0xff72, 0x11eb, 0x9a03, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03}},
+};
+const size_t kNumSpatializerEffectUuids = std::size(kSpatializerEffectUuids);
+
+constexpr float kMinAmplitude = -1.0f;
+constexpr float kMaxAmplitude = 1.0f;
+constexpr float kSNRThreshold = 100.0f;
+constexpr size_t kNumBufferSplits = 2;
+
+using SingleEffectTestParam = std::tuple<int, int, int, int, int>;
+
+class SingleEffectTest : public ::testing::TestWithParam<SingleEffectTestParam> {
+  public:
+    SingleEffectTest()
+        : mInputChMask(kSpatializerChMasks[std::get<0>(GetParam())]),
+          mInputChannelCount(audio_channel_count_from_out_mask(mInputChMask)),
+          mOutputChMask(AUDIO_CHANNEL_OUT_STEREO),
+          mOutputChannelCount(audio_channel_count_from_out_mask(mOutputChMask)),
+          mSampleRate(kSpatializerSampleRates[std::get<1>(GetParam())]),
+          mFrameCount(kSpatializerFrameCounts[std::get<2>(GetParam())]),
+          mLoopCount(EffectTestHelper::kLoopCounts[std::get<3>(GetParam())]),
+          mTotalFrameCount(mFrameCount * mLoopCount),
+          mUuid(&kSpatializerEffectUuids[std::get<4>(GetParam())]) {}
+    void SetUp() override {
+        ASSERT_EQ(AUDIO_EFFECT_LIBRARY_TAG, AUDIO_EFFECT_LIBRARY_INFO_SYM.tag)
+                << "Invalid effect tag";
+    }
+    const size_t mInputChMask;
+    const size_t mInputChannelCount;
+    const size_t mOutputChMask;
+    const size_t mOutputChannelCount;
+    const size_t mSampleRate;
+    const size_t mFrameCount;
+    const size_t mLoopCount;
+    const size_t mTotalFrameCount;
+    const effect_uuid_t* mUuid;
+};
+
+// Test basic spatializer functionality (does not crash) for various combinations of sampling
+// rates, channel masks and frame counts.
+TEST_P(SingleEffectTest, SimpleProcess) {
+    SCOPED_TRACE(testing::Message()
+                 << "chMask: " << mInputChMask << " sampleRate: " << mSampleRate);
+
+    EffectTestHelper effect(mUuid, mInputChMask, mOutputChMask, mSampleRate, mFrameCount,
+                            mLoopCount);
+    ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+    ASSERT_NO_FATAL_FAILURE(effect.setConfig());
+
+    // Initialize input buffer with deterministic pseudo-random values
+    std::vector<float> input(mTotalFrameCount * mInputChannelCount);
+    std::vector<float> output(mTotalFrameCount * mOutputChannelCount);
+    std::minstd_rand gen(mInputChMask);
+    std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
+    for (auto& in : input) {
+        in = dis(gen);
+    }
+    ASSERT_NO_FATAL_FAILURE(effect.process(input.data(), output.data()));
+    ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+INSTANTIATE_TEST_SUITE_P(SpatializerTest, SingleEffectTest,
+                         ::testing::Combine(::testing::Range(0, (int)kNumSpatializerChMasks),
+                                            ::testing::Range(0, (int)kNumSpatializerSampleRates),
+                                            ::testing::Range(0, (int)kNumSpatializerFrameCounts),
+                                            ::testing::Range(0,
+                                                             (int)EffectTestHelper::kNumLoopCounts),
+                                            ::testing::Range(0, (int)kNumSpatializerEffectUuids)));
+
+using SingleEffectComparisonTestParam = std::tuple<int, int, int>;
+
+class SingleEffectComparisonTest
+    : public ::testing::TestWithParam<SingleEffectComparisonTestParam> {
+  public:
+    SingleEffectComparisonTest()
+        : mInputChMask(kSpatializerChMasks[std::get<0>(GetParam())]),
+          mInputChannelCount(audio_channel_count_from_out_mask(mInputChMask)),
+          mOutputChMask(AUDIO_CHANNEL_OUT_STEREO),
+          mOutputChannelCount(audio_channel_count_from_out_mask(mOutputChMask)),
+          mSampleRate(kSpatializerSampleRates[std::get<1>(GetParam())]),
+          mUuid(&kSpatializerEffectUuids[std::get<2>(GetParam())]) {}
+
+    const size_t mInputChMask;
+    const size_t mInputChannelCount;
+    const size_t mOutputChMask;
+    const size_t mOutputChannelCount;
+    const size_t mSampleRate;
+    const effect_uuid_t* mUuid;
+};
+
+// Ensure that effect produces similar output when an input is fed in a single call
+// or called multiples times with buffer split into smaller parts
+
+// TODO(b/234619903): This is currently disabled as output from the spatializer has
+// an algorithm delay that varies with frame count and hence makes it tricky to
+// compare output from two cases with different frame counts.
+// Feed valid input to spatializer and dump the output to verify spatializer is being
+// correctly initialized and once that is verified, enable the following
+TEST_P(SingleEffectComparisonTest, DISABLED_SimpleProcess) {
+    SCOPED_TRACE(testing::Message()
+                 << "chMask: " << mInputChMask << " sampleRate: " << mSampleRate);
+    int testDurationMs = 20; // 20 ms
+    int testFrameCount = (mSampleRate * testDurationMs) / 1000;
+    int totalFrameCount = testFrameCount * kNumBufferSplits;
+    size_t totalInSamples = totalFrameCount * mInputChannelCount;
+    size_t totalOutSamples = totalFrameCount * mOutputChannelCount;
+    std::vector<float> input(totalInSamples);
+    std::vector<float> outRef(totalOutSamples);
+    std::vector<float> outTest(totalOutSamples);
+
+    // Initialize input buffer with deterministic pseudo-random values
+    std::minstd_rand gen(mInputChMask);
+    std::uniform_real_distribution<> dis(kMinAmplitude, kMaxAmplitude);
+    for (auto& in : input) {
+        in = dis(gen);
+    }
+
+    EffectTestHelper refEffect(mUuid, mInputChMask, mOutputChMask, mSampleRate, totalFrameCount, 1);
+    ASSERT_NO_FATAL_FAILURE(refEffect.createEffect());
+    ASSERT_NO_FATAL_FAILURE(refEffect.setConfig());
+    ASSERT_NO_FATAL_FAILURE(refEffect.process(input.data(), outRef.data()));
+    ASSERT_NO_FATAL_FAILURE(refEffect.releaseEffect());
+
+    EffectTestHelper testEffect(mUuid, mInputChMask, mOutputChMask, mSampleRate,
+                                totalFrameCount / kNumBufferSplits, kNumBufferSplits);
+    ASSERT_NO_FATAL_FAILURE(testEffect.createEffect());
+    ASSERT_NO_FATAL_FAILURE(testEffect.setConfig());
+    ASSERT_NO_FATAL_FAILURE(testEffect.process(input.data(), outTest.data()));
+    ASSERT_NO_FATAL_FAILURE(testEffect.releaseEffect());
+
+    float snr = computeSnr(outTest.data(), outRef.data(), totalOutSamples);
+    ASSERT_GT(snr, kSNRThreshold) << "SNR between reference and test output " << snr
+                                  << " is lower than required " << kSNRThreshold;
+}
+
+INSTANTIATE_TEST_SUITE_P(SpatializerTest, SingleEffectComparisonTest,
+                         ::testing::Combine(::testing::Range(0, (int)kNumSpatializerChMasks),
+                                            ::testing::Range(0, (int)kNumSpatializerSampleRates),
+                                            ::testing::Range(0, (int)kNumSpatializerEffectUuids)));
+
+// This test checks if get/set Spatializer effect params are in accordance with documentation. The
+// test doesn't validate the functionality of the params configured. It only checks the return
+// status of API calls.
+TEST(ParameterTests, CheckParameterSupport) {
+    EffectTestHelper effect(&kSpatializerEffectUuids[0], kSpatializerChMasks[0],
+                            AUDIO_CHANNEL_OUT_STEREO, kSpatializerSampleRates[0],
+                            kSpatializerFrameCounts[0], EffectTestHelper::kLoopCounts[0]);
+    ASSERT_NO_FATAL_FAILURE(effect.createEffect());
+
+    // capture list of channel masks supported
+    std::vector<audio_channel_mask_t> channelMasks;
+    int status = effect.getParam<true>(SPATIALIZER_PARAM_SUPPORTED_CHANNEL_MASKS, channelMasks);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, channelMasks.size());
+        EXPECT_EQ(AUDIO_CHANNEL_OUT_5POINT1, channelMasks[0]);
+    }
+
+    // capture list of spatialization levels supported
+    std::vector<int8_t> spatializationLevels;
+    status = effect.getParam<true>(SPATIALIZER_PARAM_SUPPORTED_LEVELS, spatializationLevels);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, spatializationLevels.size());
+        EXPECT_EQ(SPATIALIZATION_LEVEL_MULTICHANNEL, spatializationLevels[0]);
+    }
+
+    // capture list of spatialization modes supported
+    std::vector<int8_t> spatializationModes;
+    status = effect.getParam<true>(SPATIALIZER_PARAM_SUPPORTED_SPATIALIZATION_MODES,
+                                   spatializationModes);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, spatializationModes.size());
+        EXPECT_EQ(SPATIALIZATION_MODE_BINAURAL, spatializationModes[0]);
+    }
+
+    // check if head tracking is supported
+    std::vector<int8_t> headTracking;
+    status = effect.getParam<false>(SPATIALIZER_PARAM_HEADTRACKING_SUPPORTED, headTracking);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, headTracking.size());
+        EXPECT_EQ(true, headTracking[0]);
+    }
+
+    // verify spatialization level setting
+    std::vector<int8_t> level;
+    status = effect.getParam<false>(SPATIALIZER_PARAM_LEVEL, level);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, level.size());
+        EXPECT_EQ(SPATIALIZATION_LEVEL_NONE, level[0]);
+    }
+
+    ASSERT_NO_FATAL_FAILURE(effect.setConfig());
+
+    status = effect.getParam<false>(SPATIALIZER_PARAM_LEVEL, level);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, level.size());
+        EXPECT_EQ(SPATIALIZATION_LEVEL_MULTICHANNEL, level[0]);
+    }
+
+    // try setting unsupported parameters
+    level.clear();
+    level.push_back(SPATIALIZATION_LEVEL_MCHAN_BED_PLUS_OBJECTS);
+    ASSERT_EQ(1, level.size());
+    EXPECT_NE(0, effect.setParam(SPATIALIZER_PARAM_LEVEL, level));
+
+    // Ensure that unsupported level isn't set by above setParam
+    status = effect.getParam<false>(SPATIALIZER_PARAM_LEVEL, level);
+    EXPECT_EQ(status, 0) << "get Param returned an error " << status;
+    if (!status) {
+        EXPECT_EQ(1, level.size());
+        EXPECT_EQ(SPATIALIZATION_LEVEL_MULTICHANNEL, level[0]);
+    }
+
+    std::vector<float> hingeAngle = {3.1415f};
+    ASSERT_EQ(1, hingeAngle.size());
+    EXPECT_NE(0, effect.setParam(SPATIALIZER_PARAM_HINGE_ANGLE, hingeAngle));
+
+    std::vector<int8_t> headTrackingMode = {2};  // RELATIVE_WORLD
+    ASSERT_EQ(1, headTrackingMode.size());
+    EXPECT_NE(0, effect.setParam(SPATIALIZER_PARAM_HEADTRACKING_MODE, headTrackingMode));
+
+    // try setting supported parameters
+    std::vector<float> vectorFloat = {0.1, 0.2, 0.15, 0.04, 2.23, 3.14};
+    ASSERT_EQ(6, vectorFloat.size());
+    EXPECT_EQ(0, effect.setParam(SPATIALIZER_PARAM_HEAD_TO_STAGE, vectorFloat));
+
+    ASSERT_NO_FATAL_FAILURE(effect.releaseEffect());
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGD("Test result = %d\n", status);
+    return status;
+}
diff --git a/media/libeffects/tests/common/Android.bp b/media/libeffects/tests/common/Android.bp
new file mode 100644
index 0000000..73179fb
--- /dev/null
+++ b/media/libeffects/tests/common/Android.bp
@@ -0,0 +1,45 @@
+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"],
+}
+
+filegroup {
+    name: "libeffects-test-helper-srcs",
+    srcs: [
+        "EffectTestHelper.cpp",
+    ],
+}
+
+cc_library_headers {
+    name: "libeffects-test-helper-headers",
+    vendor: true,
+    host_supported: true,
+    export_include_dirs: [
+        ".",
+    ],
+}
+
+cc_defaults {
+    name: "libeffects-test-defaults",
+    vendor: true,
+    gtest: true,
+    host_supported: true,
+    test_suites: ["device-tests"],
+    static_libs: [
+        "libaudioutils",
+    ],
+    srcs: [
+        ":libeffects-test-helper-srcs",
+    ],
+    header_libs: [
+        "libeffects-test-helper-headers",
+        "libhardware_headers",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+}
diff --git a/media/libeffects/lvm/tests/EffectTestHelper.cpp b/media/libeffects/tests/common/EffectTestHelper.cpp
similarity index 97%
rename from media/libeffects/lvm/tests/EffectTestHelper.cpp
rename to media/libeffects/tests/common/EffectTestHelper.cpp
index ec727c7..db085ba 100644
--- a/media/libeffects/lvm/tests/EffectTestHelper.cpp
+++ b/media/libeffects/tests/common/EffectTestHelper.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "EffectTestHelper.h"
-extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
 
 namespace android {
 
diff --git a/media/libeffects/lvm/tests/EffectTestHelper.h b/media/libeffects/tests/common/EffectTestHelper.h
similarity index 69%
rename from media/libeffects/lvm/tests/EffectTestHelper.h
rename to media/libeffects/tests/common/EffectTestHelper.h
index bcee84e..c99e27a 100644
--- a/media/libeffects/lvm/tests/EffectTestHelper.h
+++ b/media/libeffects/tests/common/EffectTestHelper.h
@@ -21,6 +21,7 @@
 #include <audio_utils/primitives.h>
 #include <climits>
 #include <cstdlib>
+#include <dlfcn.h>
 #include <gtest/gtest.h>
 #include <hardware/audio_effect.h>
 #include <log/log.h>
@@ -29,7 +30,9 @@
 #include <system/audio.h>
 #include <vector>
 
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
 namespace android {
+
 template <typename T>
 static float computeSnr(const T* ref, const T* tst, size_t count) {
     double signal{};
@@ -82,6 +85,7 @@
     void createEffect();
     void releaseEffect();
     void setConfig();
+
     template <typename VALUE_DTYPE>
     void setParam(uint32_t type, VALUE_DTYPE const value) {
         int reply = 0;
@@ -101,6 +105,76 @@
         ASSERT_EQ(status, 0) << "set_param returned an error " << status;
         ASSERT_EQ(reply, 0) << "set_param reply non zero " << reply;
     };
+
+    template <bool MULTI_VALUES, typename T>
+    int32_t getParam(uint32_t type, std::vector<T>& values) {
+        const int kMaxEffectParamValues = 10;
+        uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1];
+        uint32_t reply[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + 1 + kMaxEffectParamValues];
+
+        effect_param_t* p = (effect_param_t*)cmd;
+        p->psize = sizeof(uint32_t);
+        if (MULTI_VALUES) {
+            p->vsize = (kMaxEffectParamValues + 1) * sizeof(T);
+        } else {
+            p->vsize = sizeof(T);
+        }
+        *(uint32_t*)p->data = type;
+        uint32_t replySize = sizeof(effect_param_t) + p->psize + p->vsize;
+
+        int32_t status = (*mEffectHandle)
+                                 ->command(mEffectHandle, EFFECT_CMD_GET_PARAM,
+                                           sizeof(effect_param_t) + sizeof(uint32_t), cmd,
+                                           &replySize, reply);
+        if (status) {
+            return status;
+        }
+        if (p->status) {
+            return p->status;
+        }
+        if (replySize <
+            sizeof(effect_param_t) + sizeof(uint32_t) + (MULTI_VALUES ? 2 : 1) * sizeof(T)) {
+            return -EINVAL;
+        }
+
+        T* params = (T*)((uint8_t*)reply + sizeof(effect_param_t) + sizeof(uint32_t));
+        int numParams = 1;
+        if (MULTI_VALUES) {
+            numParams = (int)*params++;
+        }
+        if (numParams > kMaxEffectParamValues) {
+            return -EINVAL;
+        }
+        values.clear();
+        std::copy(&params[0], &params[numParams], back_inserter(values));
+        return 0;
+    }
+
+    template <typename T>
+    int setParam(uint32_t type, const std::vector<T>& values) {
+        int reply = 0;
+        uint32_t replySize = sizeof(reply);
+
+        uint32_t cmd[sizeof(effect_param_t) / sizeof(uint32_t) + 1 + values.size()];
+        effect_param_t* p = (effect_param_t*)cmd;
+        p->psize = sizeof(uint32_t);
+        p->vsize = sizeof(T) * values.size();
+        *(uint32_t*)p->data = type;
+        memcpy((uint32_t*)p->data + 1, values.data(), sizeof(T) * values.size());
+
+        int status = (*mEffectHandle)
+                             ->command(mEffectHandle, EFFECT_CMD_SET_PARAM,
+                                       sizeof(effect_param_t) + p->psize + p->vsize, p, &replySize,
+                                       &reply);
+        if (status) {
+            return status;
+        }
+        if (reply) {
+            return reply;
+        }
+        return 0;
+    }
+
     void process(float* input, float* output);
 
     // Corresponds to SNR for 1 bit difference between two int16_t signals
diff --git a/media/libeffects/visualizer/Android.bp b/media/libeffects/visualizer/Android.bp
index 8dd6789..cf782f7 100644
--- a/media/libeffects/visualizer/Android.bp
+++ b/media/libeffects/visualizer/Android.bp
@@ -18,34 +18,60 @@
     ],
 }
 
-cc_library_shared {
-    name: "libvisualizer",
-
+cc_defaults {
+    name: "visualizer_defaults",
     vendor: true,
-
-    srcs: [
-        "EffectVisualizer.cpp",
-    ],
-
     cflags: [
-        "-O2",
-        "-fvisibility=hidden",
-
-        "-DBUILD_FLOAT",
+        "-DBUILD_FLOAT", // TODO: remove BUILD_FLOAT and SUPPORT_MC in lvm libs
         "-DSUPPORT_MC",
-
         "-Wall",
         "-Werror",
     ],
-
     shared_libs: [
         "liblog",
     ],
-
-    relative_install_path: "soundfx",
-
     header_libs: [
         "libaudioeffects",
         "libaudioutils_headers",
     ],
 }
+
+cc_library_shared {
+    name: "libvisualizer",
+    defaults: [
+        "visualizer_defaults",
+    ],
+    srcs: [
+        "EffectVisualizer.cpp",
+    ],
+    relative_install_path: "soundfx",
+    cflags: [
+        "-O2",
+        "-fvisibility=hidden",
+    ],
+}
+
+cc_library_shared {
+    name: "libvisualizeraidl",
+    srcs: [
+        "aidl/Visualizer.cpp",
+        "aidl/VisualizerContext.cpp",
+        ":effectCommonFile",
+    ],
+    defaults: [
+        "aidlaudioeffectservice_defaults",
+        "latest_android_hardware_audio_effect_ndk_shared",
+        "latest_android_media_audio_common_types_ndk_shared",
+        "visualizer_defaults",
+    ],
+    cflags: [
+        "-Wthread-safety",
+    ],
+    shared_libs: [
+        "libcutils",
+    ],
+    relative_install_path: "soundfx",
+    visibility: [
+        "//hardware/interfaces/audio/aidl/default",
+    ],
+}
diff --git a/media/libeffects/visualizer/aidl/Visualizer.cpp b/media/libeffects/visualizer/aidl/Visualizer.cpp
new file mode 100644
index 0000000..53bfb41
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_VisualizerLibEffects"
+
+#include <android-base/logging.h>
+#include <system/audio_effects/effect_uuid.h>
+
+#include "Visualizer.h"
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::getEffectImplUuidVisualizer;
+using aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::VisualizerImpl;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+                                           std::shared_ptr<IEffect>* instanceSpp) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVisualizer()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    if (instanceSpp) {
+        *instanceSpp = ndk::SharedRefBase::make<VisualizerImpl>();
+        LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+        return EX_NONE;
+    } else {
+        LOG(ERROR) << __func__ << " invalid input parameter!";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+}
+
+extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
+    if (!in_impl_uuid || *in_impl_uuid != getEffectImplUuidVisualizer()) {
+        LOG(ERROR) << __func__ << "uuid not supported";
+        return EX_ILLEGAL_ARGUMENT;
+    }
+    *_aidl_return = VisualizerImpl::kDescriptor;
+    return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+const std::string VisualizerImpl::kEffectName = "Visualizer";
+const std::vector<Range::VisualizerRange> VisualizerImpl::kRanges = {
+        MAKE_RANGE(Visualizer, latencyMs, 0, VisualizerContext::kMaxLatencyMs),
+        MAKE_RANGE(Visualizer, captureSamples, 0, VisualizerContext::kMaxCaptureBufSize),
+        /* get only parameters, set invalid range (min > max) to indicate not support set */
+        MAKE_RANGE(Visualizer, measurement, Visualizer::Measurement({.peak = 1, .rms = 1}),
+                   Visualizer::Measurement({.peak = 0, .rms = 0})),
+        MAKE_RANGE(Visualizer, captureSampleBuffer, std::vector<uint8_t>({1}),
+                   std::vector<uint8_t>({0}))};
+const Capability VisualizerImpl::kCapability = {
+        .range = Range::make<Range::visualizer>(VisualizerImpl::kRanges)};
+const Descriptor VisualizerImpl::kDescriptor = {
+        .common = {.id = {.type = getEffectTypeUuidVisualizer(),
+                          .uuid = getEffectImplUuidVisualizer(),
+                          .proxy = std::nullopt},
+                   .flags = {.type = Flags::Type::INSERT,
+                             .insert = Flags::Insert::LAST,
+                             .volume = Flags::Volume::CTRL},
+                   .name = VisualizerImpl::kEffectName,
+                   .implementor = "The Android Open Source Project"},
+        .capability = VisualizerImpl::kCapability};
+
+ndk::ScopedAStatus VisualizerImpl::getDescriptor(Descriptor* _aidl_return) {
+    RETURN_IF(!_aidl_return, EX_ILLEGAL_ARGUMENT, "Parameter:nullptr");
+    LOG(DEBUG) << __func__ << kDescriptor.toString();
+    *_aidl_return = kDescriptor;
+    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");
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    auto& param = specific.get<Parameter::Specific::visualizer>();
+    RETURN_IF(!inRange(param, kRanges), EX_ILLEGAL_ARGUMENT, "outOfRange");
+    const auto tag = param.getTag();
+    switch (tag) {
+        case Visualizer::captureSamples: {
+            RETURN_IF(mContext->setCaptureSamples(param.get<Visualizer::captureSamples>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setCaptureSizeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Visualizer::scalingMode: {
+            RETURN_IF(mContext->setScalingMode(param.get<Visualizer::scalingMode>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setScalingModeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Visualizer::measurementMode: {
+            RETURN_IF(mContext->setMeasurementMode(param.get<Visualizer::measurementMode>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setMeasurementModeFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        case Visualizer::latencyMs: {
+            RETURN_IF(mContext->setDownstreamLatency(param.get<Visualizer::latencyMs>()) !=
+                              RetCode::SUCCESS,
+                      EX_ILLEGAL_ARGUMENT, "setLatencyFailed");
+            return ndk::ScopedAStatus::ok();
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+        }
+    }
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterSpecific(const Parameter::Id& id,
+                                                        Parameter::Specific* specific) {
+    RETURN_IF(!specific, EX_NULL_POINTER, "nullPtr");
+    auto tag = id.getTag();
+    RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+    auto specificId = id.get<Parameter::Id::visualizerTag>();
+    auto specificTag = specificId.getTag();
+    switch (specificTag) {
+        case Visualizer::Id::commonTag: {
+            return getParameterVisualizer(specificId.get<Visualizer::Id::commonTag>(), specific);
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(specificTag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+                                                                    "VisualizerTagNotSupported");
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerImpl::getParameterVisualizer(const Visualizer::Tag& tag,
+                                                          Parameter::Specific* specific) {
+    RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+    Visualizer param;
+    switch (tag) {
+        case Visualizer::captureSamples: {
+            param.set<Visualizer::captureSamples>(mContext->getCaptureSamples());
+            break;
+        }
+        case Visualizer::scalingMode: {
+            param.set<Visualizer::scalingMode>(mContext->getScalingMode());
+            break;
+        }
+        case Visualizer::measurementMode: {
+            param.set<Visualizer::measurementMode>(mContext->getMeasurementMode());
+            break;
+        }
+        case Visualizer::measurement: {
+            param.set<Visualizer::measurement>(mContext->getMeasure());
+            break;
+        }
+        case Visualizer::captureSampleBuffer: {
+            param.set<Visualizer::captureSampleBuffer>(mContext->capture());
+            break;
+        }
+        case Visualizer::latencyMs: {
+            param.set<Visualizer::latencyMs>(mContext->getDownstreamLatency());
+            break;
+        }
+        default: {
+            LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+            return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+                    EX_ILLEGAL_ARGUMENT, "VisualizerTagNotSupported");
+        }
+    }
+
+    specific->set<Parameter::Specific::visualizer>(param);
+    return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VisualizerImpl::createContext(const Parameter::Common& common) {
+    if (mContext) {
+        LOG(DEBUG) << __func__ << " context already exist";
+        return mContext;
+    }
+
+    mContext = std::make_shared<VisualizerContext>(1 /* statusFmqDepth */, common);
+    mContext->initParams(common);
+    return mContext;
+}
+
+RetCode VisualizerImpl::releaseContext() {
+    if (mContext) {
+        mContext->disable();
+        mContext->resetBuffer();
+    }
+    return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VisualizerImpl::effectProcessImpl(float* in, float* out, int samples) {
+    IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+    RETURN_VALUE_IF(!mContext, status, "nullContext");
+    return mContext->process(in, out, samples);
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/Visualizer.h b/media/libeffects/visualizer/aidl/Visualizer.h
new file mode 100644
index 0000000..ec725db
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/Visualizer.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+
+#include "effect-impl/EffectImpl.h"
+
+#include "VisualizerContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerImpl final : public EffectImpl {
+  public:
+    static const std::string kEffectName;
+    static const Capability kCapability;
+    static const Descriptor kDescriptor;
+    VisualizerImpl() { LOG(DEBUG) << __func__; }
+    ~VisualizerImpl() {
+        cleanUp();
+        LOG(DEBUG) << __func__;
+    }
+
+    ndk::ScopedAStatus commandImpl(CommandId command) override;
+    ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+    ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+    ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+                                            Parameter::Specific* specific) override;
+    IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+    std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+    RetCode releaseContext() override;
+
+    std::shared_ptr<EffectContext> getContext() override { return mContext; }
+    std::string getEffectName() override { return kEffectName; }
+
+  private:
+    static const std::vector<Range::VisualizerRange> kRanges;
+    std::shared_ptr<VisualizerContext> mContext;
+    ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
+                                                    Parameter::Specific* specific);
+};
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
new file mode 100644
index 0000000..5d0d08d
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VisualizerContext.h"
+
+#include <algorithm>
+#include <math.h>
+#include <time.h>
+
+#include <android/binder_status.h>
+#include <audio_utils/primitives.h>
+#include <system/audio.h>
+#include <Utils.h>
+
+#ifndef BUILD_FLOAT
+        #error AIDL Visualizer only support float 32bits, make sure add cflags -DBUILD_FLOAT,
+#endif
+
+using aidl::android::hardware::audio::common::getChannelCount;
+
+namespace aidl::android::hardware::audio::effect {
+
+VisualizerContext::VisualizerContext(int statusDepth, const Parameter::Common& common)
+    : EffectContext(statusDepth, common) {
+}
+
+VisualizerContext::~VisualizerContext() {
+    std::lock_guard lg(mMutex);
+    LOG(DEBUG) << __func__;
+    mState = State::UNINITIALIZED;
+}
+
+RetCode VisualizerContext::initParams(const Parameter::Common& common) {
+    std::lock_guard lg(mMutex);
+    LOG(DEBUG) << __func__;
+    if (common.input != common.output) {
+        LOG(ERROR) << __func__ << " mismatch input: " << common.input.toString()
+                   << " and output: " << common.output.toString();
+        return RetCode::ERROR_ILLEGAL_PARAMETER;
+    }
+
+    mState = State::INITIALIZED;
+    auto channelCount = getChannelCount(common.input.base.channelMask);
+#ifdef SUPPORT_MC
+    if (channelCount < 1 || channelCount > FCC_LIMIT) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#else
+    if (channelCount != FCC_2) return RetCode::ERROR_ILLEGAL_PARAMETER;
+#endif
+    mChannelCount = channelCount;
+    mCommon = common;
+    return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::enable() {
+    std::lock_guard lg(mMutex);
+    if (mState != State::INITIALIZED) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = State::ACTIVE;
+    return RetCode::SUCCESS;
+}
+
+RetCode VisualizerContext::disable() {
+    std::lock_guard lg(mMutex);
+    if (mState != State::ACTIVE) {
+        return RetCode::ERROR_EFFECT_LIB_ERROR;
+    }
+    mState = State::INITIALIZED;
+    return RetCode::SUCCESS;
+}
+
+void VisualizerContext::reset() {
+    std::lock_guard lg(mMutex);
+    std::fill_n(mCaptureBuf.begin(), kMaxCaptureBufSize, 0x80);
+}
+
+RetCode VisualizerContext::setCaptureSamples(int samples) {
+    std::lock_guard lg(mMutex);
+    mCaptureSamples = samples;
+    return RetCode::SUCCESS;
+}
+int VisualizerContext::getCaptureSamples() {
+    std::lock_guard lg(mMutex);
+    return mCaptureSamples;
+}
+
+RetCode VisualizerContext::setMeasurementMode(Visualizer::MeasurementMode mode) {
+    std::lock_guard lg(mMutex);
+    mMeasurementMode = mode;
+    return RetCode::SUCCESS;
+}
+Visualizer::MeasurementMode VisualizerContext::getMeasurementMode() {
+    std::lock_guard lg(mMutex);
+    return mMeasurementMode;
+}
+
+RetCode VisualizerContext::setScalingMode(Visualizer::ScalingMode mode) {
+    std::lock_guard lg(mMutex);
+    mScalingMode = mode;
+    return RetCode::SUCCESS;
+}
+Visualizer::ScalingMode VisualizerContext::getScalingMode() {
+    std::lock_guard lg(mMutex);
+    return mScalingMode;
+}
+
+RetCode VisualizerContext::setDownstreamLatency(int latency) {
+    std::lock_guard lg(mMutex);
+    mDownstreamLatency = latency;
+    return RetCode::SUCCESS;
+}
+
+int VisualizerContext::getDownstreamLatency() {
+    std::lock_guard lg(mMutex);
+    return mDownstreamLatency;
+}
+
+uint32_t VisualizerContext::getDeltaTimeMsFromUpdatedTime_l() {
+    uint32_t deltaMs = 0;
+    if (mBufferUpdateTime.tv_sec != 0) {
+        struct timespec ts;
+        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
+            time_t secs = ts.tv_sec - mBufferUpdateTime.tv_sec;
+            long nsec = ts.tv_nsec - mBufferUpdateTime.tv_nsec;
+            if (nsec < 0) {
+                --secs;
+                nsec += 1000000000;
+            }
+            deltaMs = secs * 1000 + nsec / 1000000;
+        }
+    }
+    return deltaMs;
+}
+
+Visualizer::Measurement VisualizerContext::getMeasure() {
+    uint16_t peakU16 = 0;
+    float sumRmsSquared = 0.0f;
+    uint8_t nbValidMeasurements = 0;
+
+    {
+        std::lock_guard lg(mMutex);
+        // reset measurements if last measurement was too long ago (which implies stored
+        // measurements aren't relevant anymore and shouldn't bias the new one)
+        const uint32_t delayMs = getDeltaTimeMsFromUpdatedTime_l();
+        if (delayMs > kDiscardMeasurementsTimeMs) {
+            LOG(INFO) << __func__ << " Discarding " << delayMs << " ms old measurements";
+            for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+                mPastMeasurements[i].mIsValid = false;
+                mPastMeasurements[i].mPeakU16 = 0;
+                mPastMeasurements[i].mRmsSquared = 0;
+            }
+            mMeasurementBufferIdx = 0;
+        } else {
+            // only use actual measurements, otherwise the first RMS measure happening before
+            // MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially
+            // low
+            for (uint32_t i = 0; i < mMeasurementWindowSizeInBuffers; i++) {
+                if (mPastMeasurements[i].mIsValid) {
+                    if (mPastMeasurements[i].mPeakU16 > peakU16) {
+                        peakU16 = mPastMeasurements[i].mPeakU16;
+                    }
+                    sumRmsSquared += mPastMeasurements[i].mRmsSquared;
+                    nbValidMeasurements++;
+                }
+            }
+        }
+    }
+
+    float rms = nbValidMeasurements == 0 ? 0.0f : sqrtf(sumRmsSquared / nbValidMeasurements);
+    Visualizer::Measurement measure;
+    // convert from I16 sample values to mB and write results
+    measure.rms = (rms < 0.000016f) ? -9600 : (int32_t)(2000 * log10(rms / 32767.0f));
+    measure.peak = (peakU16 == 0) ? -9600 : (int32_t)(2000 * log10(peakU16 / 32767.0f));
+    LOG(INFO) << __func__ << " peak " << peakU16 << " (" << measure.peak << "mB), rms " << rms
+              << " (" << measure.rms << "mB)";
+    return measure;
+}
+
+std::vector<uint8_t> VisualizerContext::capture() {
+    std::vector<uint8_t> result;
+    std::lock_guard lg(mMutex);
+    // cts android.media.audio.cts.VisualizerTest expecting silence data when effect not running
+    // RETURN_VALUE_IF(mState != State::ACTIVE, result, "illegalState");
+    if (mState != State::ACTIVE) {
+        result.resize(mCaptureSamples);
+        memset(result.data(), 0x80, mCaptureSamples);
+        return result;
+    }
+
+    const uint32_t deltaMs = getDeltaTimeMsFromUpdatedTime_l();
+    // if audio framework has stopped playing audio although the effect is still active we must
+    // clear the capture buffer to return silence
+    if ((mLastCaptureIdx == mCaptureIdx) && (mBufferUpdateTime.tv_sec != 0) &&
+        (deltaMs > kMaxStallTimeMs)) {
+        LOG(INFO) << __func__ << " capture going to idle";
+        mBufferUpdateTime.tv_sec = 0;
+        return result;
+    }
+    int32_t latencyMs = mDownstreamLatency;
+    latencyMs -= deltaMs;
+    if (latencyMs < 0) {
+        latencyMs = 0;
+    }
+    uint32_t deltaSamples = mCaptureSamples + mCommon.input.base.sampleRate * latencyMs / 1000;
+
+    // large sample rate, latency, or capture size, could cause overflow.
+    // do not offset more than the size of buffer.
+    if (deltaSamples > kMaxCaptureBufSize) {
+        android_errorWriteLog(0x534e4554, "31781965");
+        deltaSamples = kMaxCaptureBufSize;
+    }
+
+    int32_t capturePoint;
+    //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
+    __builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
+    // a negative capturePoint means we wrap the buffer.
+    if (capturePoint < 0) {
+        uint32_t size = -capturePoint;
+        if (size > mCaptureSamples) {
+            size = mCaptureSamples;
+        }
+        result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
+                        &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
+        mCaptureSamples -= size;
+        capturePoint = 0;
+    }
+    result.insert(result.end(), &mCaptureBuf[capturePoint],
+                    &mCaptureBuf[capturePoint + mCaptureSamples]);
+    mLastCaptureIdx = mCaptureIdx;
+    return result;
+}
+
+IEffect::Status VisualizerContext::process(float* in, float* out, int samples) {
+    IEffect::Status result = {STATUS_NOT_ENOUGH_DATA, 0, 0};
+    RETURN_VALUE_IF(in == nullptr || out == nullptr || samples == 0, result, "dataBufferError");
+
+    std::lock_guard lg(mMutex);
+    result.status = STATUS_INVALID_OPERATION;
+    RETURN_VALUE_IF(mState != State::ACTIVE, result, "stateNotActive");
+    LOG(DEBUG) << __func__ << " in " << in << " out " << out << " sample " << samples;
+    // perform measurements if needed
+    if (mMeasurementMode == Visualizer::MeasurementMode::PEAK_RMS) {
+        // find the peak and RMS squared for the new buffer
+        float rmsSqAcc = 0;
+        float maxSample = 0.f;
+        for (size_t inIdx = 0; inIdx < (unsigned)samples; ++inIdx) {
+            maxSample = fmax(maxSample, fabs(in[inIdx]));
+            rmsSqAcc += in[inIdx] * in[inIdx];
+        }
+        maxSample *= 1 << 15; // scale to int16_t, with exactly 1 << 15 representing positive num.
+        rmsSqAcc *= 1 << 30; // scale to int16_t * 2
+        mPastMeasurements[mMeasurementBufferIdx] = {
+                .mPeakU16 = (uint16_t)maxSample,
+                .mRmsSquared = rmsSqAcc / samples,
+                .mIsValid = true };
+        if (++mMeasurementBufferIdx >= mMeasurementWindowSizeInBuffers) {
+            mMeasurementBufferIdx = 0;
+        }
+    }
+
+    float fscale;  // multiplicative scale
+    if (mScalingMode == Visualizer::ScalingMode::NORMALIZED) {
+        // derive capture scaling factor from peak value in current buffer
+        // this gives more interesting captures for display.
+        float maxSample = 0.f;
+        for (size_t inIdx = 0; inIdx < (unsigned)samples; ) {
+            // we reconstruct the actual summed value to ensure proper normalization
+            // for multichannel outputs (channels > 2 may often be 0).
+            float smp = 0.f;
+            for (int i = 0; i < mChannelCount; ++i) {
+                smp += in[inIdx++];
+            }
+            maxSample = fmax(maxSample, fabs(smp));
+        }
+        if (maxSample > 0.f) {
+            fscale = 0.99f / maxSample;
+            int exp; // unused
+            const float significand = frexp(fscale, &exp);
+            if (significand == 0.5f) {
+                fscale *= 255.f / 256.f; // avoid returning unaltered PCM signal
+            }
+        } else {
+            // scale doesn't matter, the values are all 0.
+            fscale = 1.f;
+        }
+    } else {
+        assert(mScalingMode == Visualizer::ScalingMode::AS_PLAYED);
+        // Note: if channels are uncorrelated, 1/sqrt(N) could be used at the risk of clipping.
+        fscale = 1.f / mChannelCount;  // account for summing all the channels together.
+    }
+
+    uint32_t captIdx;
+    uint32_t inIdx;
+    for (inIdx = 0, captIdx = mCaptureIdx; inIdx < (unsigned)samples; captIdx++) {
+        // wrap
+        if (captIdx >= kMaxCaptureBufSize) {
+            captIdx = 0;
+        }
+
+        float smp = 0.f;
+        for (uint32_t i = 0; i < mChannelCount; ++i) {
+            smp += in[inIdx++];
+        }
+        mCaptureBuf[captIdx] = clamp8_from_float(smp * fscale);
+    }
+
+    // the following two should really be atomic, though it probably doesn't
+    // matter much for visualization purposes
+    mCaptureIdx = captIdx;
+    // update last buffer update time stamp
+    if (clock_gettime(CLOCK_MONOTONIC, &mBufferUpdateTime) < 0) {
+        mBufferUpdateTime.tv_sec = 0;
+    }
+
+    // TODO: handle access_mode
+    memcpy(out, in, samples * sizeof(float));
+    return {STATUS_OK, samples, samples};
+}
+
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.h b/media/libeffects/visualizer/aidl/VisualizerContext.h
new file mode 100644
index 0000000..958035f
--- /dev/null
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android-base/thread_annotations.h>
+#include <audio_effects/effect_dynamicsprocessing.h>
+
+#include "effect-impl/EffectContext.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerContext final : public EffectContext {
+  public:
+    static const uint32_t kMaxCaptureBufSize = 65536;
+    static const uint32_t kMaxLatencyMs = 3000;  // 3 seconds of latency for audio pipeline
+
+    VisualizerContext(int statusDepth, const Parameter::Common& common);
+    ~VisualizerContext();
+
+    RetCode initParams(const Parameter::Common& common);
+
+    RetCode enable();
+    RetCode disable();
+    // keep all parameters and reset buffer.
+    void reset();
+
+    RetCode setCaptureSamples(int captureSize);
+    int getCaptureSamples();
+    RetCode setMeasurementMode(Visualizer::MeasurementMode mode);
+    Visualizer::MeasurementMode getMeasurementMode();
+    RetCode setScalingMode(Visualizer::ScalingMode mode);
+    Visualizer::ScalingMode getScalingMode();
+    RetCode setDownstreamLatency(int latency);
+    int getDownstreamLatency();
+
+    IEffect::Status process(float* in, float* out, int samples);
+    // Gets the current measurements, measured by process() and consumed by getParameter()
+    Visualizer::Measurement getMeasure();
+    // Gets the latest PCM capture, data captured by process() and consumed by getParameter()
+    std::vector<uint8_t> capture();
+
+    struct BufferStats {
+        bool mIsValid;
+        uint16_t mPeakU16; // the positive peak of the absolute value of the samples in a buffer
+        float mRmsSquared; // the average square of the samples in a buffer
+    };
+
+    enum State {
+        UNINITIALIZED,
+        INITIALIZED,
+        ACTIVE,
+    };
+
+  private:
+    // maximum time since last capture buffer update before resetting capture buffer. This means
+    // that the framework has stopped playing audio and we must start returning silence
+    static const uint32_t kMaxStallTimeMs = 1000;
+    // discard measurements older than this number of ms
+    static const uint32_t kDiscardMeasurementsTimeMs = 2000;
+    // maximum number of buffers for which we keep track of the measurements
+    // note: buffer index is stored in uint8_t
+    static const uint32_t kMeasurementWindowMaxSizeInBuffers = 25;
+
+    // serialize process() and parameter setting
+    std::mutex mMutex;
+    Parameter::Common mCommon GUARDED_BY(mMutex);
+    State mState GUARDED_BY(mMutex) = State::UNINITIALIZED;
+    uint32_t mCaptureIdx GUARDED_BY(mMutex) = 0;
+    uint32_t mLastCaptureIdx GUARDED_BY(mMutex) = 0;
+    Visualizer::ScalingMode mScalingMode GUARDED_BY(mMutex) = Visualizer::ScalingMode::NORMALIZED;
+    struct timespec mBufferUpdateTime GUARDED_BY(mMutex);
+    // capture buf with 8 bits mono PCM samples
+    std::array<uint8_t, kMaxCaptureBufSize> mCaptureBuf GUARDED_BY(mMutex);
+    uint32_t mDownstreamLatency GUARDED_BY(mMutex) = 0;
+    uint32_t mCaptureSamples GUARDED_BY(mMutex) = kMaxCaptureBufSize;
+
+    // to avoid recomputing it every time a buffer is processed
+    uint8_t mChannelCount GUARDED_BY(mMutex) = 0;
+    Visualizer::MeasurementMode mMeasurementMode GUARDED_BY(mMutex) =
+            Visualizer::MeasurementMode::NONE;
+    uint8_t mMeasurementWindowSizeInBuffers = kMeasurementWindowMaxSizeInBuffers;
+    uint8_t mMeasurementBufferIdx GUARDED_BY(mMutex) = 0;
+    std::array<BufferStats, kMeasurementWindowMaxSizeInBuffers> mPastMeasurements;
+    void init_params();
+
+    uint32_t getDeltaTimeMsFromUpdatedTime_l() REQUIRES(mMutex);
+};
+}  // namespace aidl::android::hardware::audio::effect
diff --git a/media/liberror/Android.bp b/media/liberror/Android.bp
index f54d354..5e94b0a 100644
--- a/media/liberror/Android.bp
+++ b/media/liberror/Android.bp
@@ -25,7 +25,7 @@
     ],
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media",
         "com.android.media.swcodec",
     ],
@@ -51,7 +51,7 @@
     min_sdk_version: "29",
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 2dd5784..590a7b7 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -304,6 +304,10 @@
 cc_library {
     name: "libmedia",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     srcs: [
         ":mediaextractorservice_aidl",
         "IDataSource.cpp",
@@ -356,7 +360,6 @@
 
     shared_libs: [
         "android.hidl.token@1.0-utils",
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "av-types-aidl-cpp",
         "liblog",
@@ -381,7 +384,6 @@
     export_shared_lib_headers: [
         "libaudioclient",
         "libbinder",
-        "libandroidicu",
         //"libsonivox",
         "libmedia_omx",
         "framework-permission-aidl-cpp",
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 154988d..e191999 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -428,7 +428,7 @@
         return reply.readInt32();
     }
 
-    status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+    status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones)
     {
         ALOGV("getActiveMicrophones");
         Parcel data, reply;
@@ -756,7 +756,7 @@
         case GET_ACTIVE_MICROPHONES: {
             ALOGV("GET_ACTIVE_MICROPHONES");
             CHECK_INTERFACE(IMediaRecorder, data, reply);
-            std::vector<media::MicrophoneInfo> activeMicrophones;
+            std::vector<media::MicrophoneInfoFw> activeMicrophones;
             status_t status = getActiveMicrophones(&activeMicrophones);
             reply->writeInt32(status);
             if (status != NO_ERROR) {
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 85768bd..5aa9adc 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -898,10 +898,9 @@
         }
     }
 
-    for (size_t cameraId = 0; cameraId < mCameraIds.size(); ++cameraId) {
+    for (size_t refIndex = 0; refIndex < mCameraIds.size(); ++refIndex) {
+        const int cameraId = mCameraIds[refIndex];
         for (size_t j = 0; j < kNumRequiredProfiles; ++j) {
-            int refIndex = getRequiredProfileRefIndex(cameraId);
-            CHECK(refIndex != -1);
             RequiredProfileRefInfo *info =
                     &mRequiredProfileRefs[refIndex].mRefs[j];
 
@@ -931,14 +930,14 @@
 
                 int index = getCamcorderProfileIndex(cameraId, profile->mQuality);
                 if (index != -1) {
-                    ALOGV("Profile quality %d for camera %zu already exists",
+                    ALOGV("Profile quality %d for camera %d already exists",
                         profile->mQuality, cameraId);
                     CHECK(index == refIndex);
                     continue;
                 }
 
                 // Insert the new profile
-                ALOGV("Add a profile: quality %d=>%d for camera %zu",
+                ALOGV("Add a profile: quality %d=>%d for camera %d",
                         mCamcorderProfiles[info->mRefProfileIndex]->mQuality,
                         profile->mQuality, cameraId);
 
diff --git a/media/libmedia/include/media/CharacterEncodingDetector.h b/media/libmedia/include/media/CharacterEncodingDetector.h
index 62564b1..2acc868 100644
--- a/media/libmedia/include/media/CharacterEncodingDetector.h
+++ b/media/libmedia/include/media/CharacterEncodingDetector.h
@@ -21,9 +21,12 @@
 
 #include "StringArray.h"
 
-#include "unicode/ucnv.h"
-#include "unicode/ucsdet.h"
-#include "unicode/ustring.h"
+/** Declare opaque structures from ICU4C. */
+struct UConverter;
+typedef struct UConverter UConverter;
+
+struct UCharsetMatch;
+typedef struct UCharsetMatch UCharsetMatch;
 
 namespace android {
 
diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h
index 6e69782..05da5c2 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -18,8 +18,8 @@
 #ifndef ANDROID_IMEDIARECORDER_H
 #define ANDROID_IMEDIARECORDER_H
 
+#include <android/media/MicrophoneInfoFw.h>
 #include <binder/IInterface.h>
-#include <media/MicrophoneInfo.h>
 #include <system/audio.h>
 #include <vector>
 
@@ -74,7 +74,7 @@
     virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0;
     virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
     virtual status_t getActiveMicrophones(
-                        std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+                        std::vector<media::MicrophoneInfoFw>* activeMicrophones) = 0;
     virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
     virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
     virtual status_t getPortId(audio_port_handle_t *portId) = 0;
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index 2b7818d..82ec9c5 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -19,7 +19,6 @@
 #define MEDIA_RECORDER_BASE_H_
 
 #include <media/AudioSystem.h>
-#include <media/MicrophoneInfo.h>
 #include <media/mediarecorder.h>
 #include <android/content/AttributionSourceState.h>
 
@@ -74,7 +73,7 @@
     virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback) = 0;
     virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
     virtual status_t getActiveMicrophones(
-                        std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+                        std::vector<media::MicrophoneInfoFw>* activeMicrophones) = 0;
     virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
     virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
     virtual status_t getPortId(audio_port_handle_t *portId) const = 0;
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index dd18144..602f72e 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -24,7 +24,7 @@
 #include <utils/Errors.h>
 #include <media/IMediaRecorderClient.h>
 #include <media/IMediaDeathNotifier.h>
-#include <media/MicrophoneInfo.h>
+#include <android/media/MicrophoneInfoFw.h>
 #include <android/content/AttributionSourceState.h>
 
 namespace android {
@@ -268,7 +268,7 @@
     status_t    setInputDevice(audio_port_handle_t deviceId);
     status_t    getRoutedDeviceId(audio_port_handle_t *deviceId);
     status_t    enableAudioDeviceCallback(bool enabled);
-    status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+    status_t    getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
     status_t    setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
     status_t    setPreferredMicrophoneFieldDimension(float zoom);
 
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index cf12c36..bd06fb6 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -884,7 +884,8 @@
     return mMediaRecorder->enableAudioDeviceCallback(enabled);
 }
 
-status_t MediaRecorder::getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
+status_t MediaRecorder::getActiveMicrophones(
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones)
 {
     ALOGV("getActiveMicrophones");
 
diff --git a/media/libmedia/tests/codeclist/CodecListTest.cpp b/media/libmedia/tests/codeclist/CodecListTest.cpp
index bd2adf7..75adcca 100644
--- a/media/libmedia/tests/codeclist/CodecListTest.cpp
+++ b/media/libmedia/tests/codeclist/CodecListTest.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "CodecListTest"
 #include <utils/Log.h>
 
+#include <memory>
+
 #include <gtest/gtest.h>
 
 #include <binder/Parcel.h>
@@ -194,16 +196,15 @@
             }
         }
 
-        Parcel *codecInfoParcel = new Parcel();
+        std::unique_ptr<Parcel> codecInfoParcel(new Parcel());
         ASSERT_NE(codecInfoParcel, nullptr) << "Unable to create parcel";
 
-        status_t status = info->writeToParcel(codecInfoParcel);
+        status_t status = info->writeToParcel(codecInfoParcel.get());
         ASSERT_EQ(status, OK) << "Writing to parcel failed";
 
         codecInfoParcel->setDataPosition(0);
         sp<MediaCodecInfo> parcelCodecInfo = info->FromParcel(*codecInfoParcel);
         ASSERT_NE(parcelCodecInfo, nullptr) << "CodecInfo from parcel is null";
-        delete codecInfoParcel;
 
         EXPECT_STREQ(info->getCodecName(), parcelCodecInfo->getCodecName())
                 << "Returned codec name in info doesn't match";
diff --git a/media/libmediahelper/Android.bp b/media/libmediahelper/Android.bp
index 165a8ad..c66861b 100644
--- a/media/libmediahelper/Android.bp
+++ b/media/libmediahelper/Android.bp
@@ -20,7 +20,7 @@
     },
     apex_available: [
         "//apex_available:platform",
-        "com.android.bluetooth",
+        "com.android.btservices",
         "com.android.media",
         "com.android.media.swcodec",
     ],
diff --git a/media/libmediahelper/AudioParameter.cpp b/media/libmediahelper/AudioParameter.cpp
index 382a920..9a8156e 100644
--- a/media/libmediahelper/AudioParameter.cpp
+++ b/media/libmediahelper/AudioParameter.cpp
@@ -61,6 +61,12 @@
         AUDIO_PARAMETER_DEVICE_ADDITIONAL_OUTPUT_DELAY;
 const char * const AudioParameter::keyMaxAdditionalOutputDeviceDelay =
         AUDIO_PARAMETER_DEVICE_MAX_ADDITIONAL_OUTPUT_DELAY;
+const char * const AudioParameter::keyOffloadCodecAverageBitRate = AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE;
+const char * const AudioParameter::keyOffloadCodecSampleRate = AUDIO_OFFLOAD_CODEC_SAMPLE_RATE;
+const char * const AudioParameter::keyOffloadCodecChannels = AUDIO_OFFLOAD_CODEC_NUM_CHANNEL;
+const char * const AudioParameter::keyOffloadCodecDelaySamples = AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES;
+const char * const AudioParameter::keyOffloadCodecPaddingSamples =
+        AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES;
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
@@ -226,4 +232,9 @@
     }
 }
 
+bool AudioParameter::containsKey(const String8& key) const
+{
+    return mParameters.indexOfKey(key) >= 0;
+}
+
 } // namespace android
diff --git a/media/libmediahelper/include/media/AudioParameter.h b/media/libmediahelper/include/media/AudioParameter.h
index 9a6ca8a..41aff7c 100644
--- a/media/libmediahelper/include/media/AudioParameter.h
+++ b/media/libmediahelper/include/media/AudioParameter.h
@@ -107,6 +107,12 @@
     static const char * const keyAdditionalOutputDeviceDelay;
     static const char * const keyMaxAdditionalOutputDeviceDelay;
 
+    static const char * const keyOffloadCodecAverageBitRate;
+    static const char * const keyOffloadCodecSampleRate;
+    static const char * const keyOffloadCodecChannels;
+    static const char * const keyOffloadCodecDelaySamples;
+    static const char * const keyOffloadCodecPaddingSamples;
+
     String8 toString() const { return toStringImpl(true); }
     String8 keysToString() const { return toStringImpl(false); }
 
@@ -117,6 +123,12 @@
 
     status_t remove(const String8& key);
 
+    status_t get(const String8& key, int& value) const {
+        return getInt(key, value);
+    }
+    status_t get(const String8& key, float& value) const {
+        return getFloat(key, value);
+    }
     status_t get(const String8& key, String8& value) const;
     status_t getInt(const String8& key, int& value) const;
     status_t getFloat(const String8& key, float& value) const;
@@ -125,6 +137,7 @@
 
     size_t size() const { return mParameters.size(); }
 
+    bool containsKey(const String8& key) const;
 private:
     String8 mKeyValuePairs;
     KeyedVector <String8, String8> mParameters;
diff --git a/media/libmediametrics/libmediametrics.map.txt b/media/libmediametrics/libmediametrics.map.txt
index c46281a..f37af64 100644
--- a/media/libmediametrics/libmediametrics.map.txt
+++ b/media/libmediametrics/libmediametrics.map.txt
@@ -1,29 +1,29 @@
 LIBMEDIAMETRICS_1 {
   global:
-    mediametrics_addDouble; # apex
-    mediametrics_addInt32; # apex
-    mediametrics_addInt64; # apex
-    mediametrics_addRate; # apex
-    mediametrics_count; # apex
-    mediametrics_create; # apex
-    mediametrics_delete; # apex
-    mediametrics_freeCString; # apex
-    mediametrics_getAttributes; # apex
-    mediametrics_getCString; # apex
-    mediametrics_getDouble; # apex
-    mediametrics_getInt32; # apex
-    mediametrics_getInt64; # apex
-    mediametrics_getKey; # apex
-    mediametrics_getRate; # apex
-    mediametrics_isEnabled; # apex
-    mediametrics_readable; # apex
-    mediametrics_selfRecord; # apex
-    mediametrics_setCString; # apex
-    mediametrics_setDouble; # apex
-    mediametrics_setInt32; # apex
-    mediametrics_setInt64; # apex
-    mediametrics_setRate; # apex
-    mediametrics_setUid; # apex
+    mediametrics_addDouble; # systemapi
+    mediametrics_addInt32; # systemapi
+    mediametrics_addInt64; # systemapi
+    mediametrics_addRate; # systemapi
+    mediametrics_count; # systemapi
+    mediametrics_create; # systemapi
+    mediametrics_delete; # systemapi
+    mediametrics_freeCString; # systemapi
+    mediametrics_getAttributes; # systemapi
+    mediametrics_getCString; # systemapi
+    mediametrics_getDouble; # systemapi
+    mediametrics_getInt32; # systemapi
+    mediametrics_getInt64; # systemapi
+    mediametrics_getKey; # systemapi
+    mediametrics_getRate; # systemapi
+    mediametrics_isEnabled; # systemapi
+    mediametrics_readable; # systemapi
+    mediametrics_selfRecord; # systemapi
+    mediametrics_setCString; # systemapi
+    mediametrics_setDouble; # systemapi
+    mediametrics_setInt32; # systemapi
+    mediametrics_setInt64; # systemapi
+    mediametrics_setRate; # systemapi
+    mediametrics_setUid; # systemapi
   local:
     *;
 };
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8e19d02..fdcf246 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2683,7 +2683,7 @@
     // This is a benign busy-wait, with the next data request generated 10 ms or more later;
     // nevertheless for power reasons, we don't want to see too many of these.
 
-    ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned");
+    ALOGV_IF(actualSize == 0 && buffer.size() > 0, "callbackwrapper: empty buffer returned");
     unlock();
     return actualSize;
 }
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 4aa80be..58fc06d 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -563,7 +563,7 @@
 }
 
 status_t MediaRecorderClient::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
     ALOGV("getActiveMicrophones");
     Mutex::Autolock lock(mLock);
     if (mRecorder != NULL) {
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index dcb9f82..dec0c99 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -83,7 +83,7 @@
     virtual     status_t   getRoutedDeviceId(audio_port_handle_t* deviceId);
     virtual     status_t   enableAudioDeviceCallback(bool enabled);
     virtual     status_t   getActiveMicrophones(
-                              std::vector<media::MicrophoneInfo>* activeMicrophones);
+                              std::vector<media::MicrophoneInfoFw>* activeMicrophones);
     virtual     status_t   setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
     virtual     status_t   setPreferredMicrophoneFieldDimension(float zoom);
                 status_t   getPortId(audio_port_handle_t *portId) override;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 6497b58..ec79b99 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -2576,7 +2576,7 @@
 }
 
 status_t StagefrightRecorder::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
     if (mAudioSourceNode != 0) {
         return mAudioSourceNode->getActiveMicrophones(activeMicrophones);
     }
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 0801101..0b6a5bb 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -83,7 +83,7 @@
     virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId);
     virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
     virtual status_t enableAudioDeviceCallback(bool enabled);
-    virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+    virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
     virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
     virtual status_t setPreferredMicrophoneFieldDimension(float zoom);
             status_t getPortId(audio_port_handle_t *portId) const override;
diff --git a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
index b0040fe..43b3c37 100644
--- a/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
+++ b/media/libmediaplayerservice/fuzzer/mediarecorder_fuzzer.cpp
@@ -193,7 +193,7 @@
     mStfRecorder->setInputDevice(deviceId);
     mStfRecorder->getRoutedDeviceId(&deviceId);
 
-    vector<android::media::MicrophoneInfo> activeMicrophones{};
+    vector<android::media::MicrophoneInfoFw> activeMicrophones{};
     mStfRecorder->getActiveMicrophones(&activeMicrophones);
 
     int32_t portId;
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 71a3168..911463b 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -17,6 +17,14 @@
     ],
 }
 
+cc_library_headers {
+    name: "libstagefright_nuplayer_headers",
+
+    export_include_dirs: [
+        "include",
+    ],
+}
+
 cc_library_static {
 
     srcs: [
@@ -81,6 +89,7 @@
 
     static_libs: [
         "libplayerservice_datasource",
+        "libstagefright_esds",
         "libstagefright_timedtext",
     ],
 
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 9b4fc8f..d205990 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -60,7 +60,7 @@
 #include <gui/Surface.h>
 
 
-#include "ESDS.h"
+#include <media/esds/ESDS.h>
 #include <media/stagefright/Utils.h>
 
 namespace android {
@@ -1220,7 +1220,11 @@
                             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
                         } else {
                             // Only audio track has error. Video track could be still good to play.
-                            notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
+                            if (mVideoEOS) {
+                                notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+                            } else {
+                                notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_AUDIO_ERROR, err);
+                            }
                         }
                         mAudioDecoderError = true;
                     } else {
@@ -1231,7 +1235,11 @@
                             notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
                         } else {
                             // Only video track has error. Audio track could be still good to play.
-                            notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
+                            if (mAudioEOS) {
+                                notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+                            } else {
+                                notifyListener(MEDIA_INFO, MEDIA_INFO_PLAY_VIDEO_ERROR, err);
+                            }
                         }
                         mVideoDecoderError = true;
                     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
index 5e29b3f..a964d4f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDrm.cpp
@@ -22,14 +22,13 @@
 #include <mediadrm/DrmUtils.h>
 #include <utils/Log.h>
 
-
 namespace android {
 
 // static helpers - internal
 
 sp<IDrm> NuPlayerDrm::CreateDrm(status_t *pstatus)
 {
-    return DrmUtils::MakeDrm(pstatus);
+    return DrmUtils::MakeDrm(IDRM_NUPLAYER, pstatus);
 }
 
 sp<ICrypto> NuPlayerDrm::createCrypto(status_t *pstatus)
diff --git a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
index 162c187..9514021 100644
--- a/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
+++ b/media/libmediaplayerservice/tests/stagefrightRecorder/StagefrightRecorderTest.cpp
@@ -286,7 +286,7 @@
     // Record media for 4 secs
     std::this_thread::sleep_for(std::chrono::seconds(kClipDurationInSec));
 
-    std::vector<media::MicrophoneInfo> activeMicrophones{};
+    std::vector<media::MicrophoneInfoFw> activeMicrophones{};
     status = mStfRecorder->getActiveMicrophones(&activeMicrophones);
     ASSERT_EQ(status, OK) << "Failed to get Active Microphones";
     ASSERT_GT(activeMicrophones.size(), 0) << "No active microphones are found";
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 52c4c0f..ccbe995 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -785,7 +785,7 @@
 
     // we cannot change the number of output buffers while OMX is running
     // set up surface to the same count
-    Vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
+    std::vector<BufferInfo> &buffers = mBuffers[kPortIndexOutput];
     ALOGV("setting up surface for %zu buffers", buffers.size());
 
     err = native_window_set_buffer_count(nativeWindow, buffers.size());
@@ -825,7 +825,7 @@
     // cancel undequeued buffers to new surface
     if (!storingMetadataInDecodedBuffers()) {
         for (size_t i = 0; i < buffers.size(); ++i) {
-            BufferInfo &info = buffers.editItemAt(i);
+            BufferInfo &info = buffers[i];
             if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
                 ALOGV("canceling buffer %p", info.mGraphicBuffer->getNativeBuffer());
                 err = nativeWindow->cancelBuffer(
@@ -872,7 +872,7 @@
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
 
     CHECK(mAllocator[portIndex] == NULL);
-    CHECK(mBuffers[portIndex].isEmpty());
+    CHECK(mBuffers[portIndex].empty());
 
     status_t err;
     if (mNativeWindow != NULL && portIndex == kPortIndexOutput) {
@@ -951,6 +951,7 @@
 
             const sp<AMessage> &format =
                     portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
+            mBuffers[portIndex].reserve(def.nBufferCountActual);
             for (OMX_U32 i = 0; i < def.nBufferCountActual && err == OK; ++i) {
                 hidl_memory hidlMemToken;
                 sp<TMemory> hidlMem;
@@ -1039,7 +1040,7 @@
                     }
                 }
 
-                mBuffers[portIndex].push(info);
+                mBuffers[portIndex].push_back(info);
             }
         }
     }
@@ -1250,6 +1251,7 @@
          mComponentName.c_str(), bufferCount, bufferSize);
 
     // Dequeue buffers and send them to OMX
+    mBuffers[kPortIndexOutput].reserve(bufferCount);
     for (OMX_U32 i = 0; i < bufferCount; i++) {
         ANativeWindowBuffer *buf;
         int fenceFd;
@@ -1275,7 +1277,7 @@
         info.mData = new MediaCodecBuffer(mOutputFormat, new ABuffer(bufferSize));
         info.mCodecData = info.mData;
 
-        mBuffers[kPortIndexOutput].push(info);
+        mBuffers[kPortIndexOutput].push_back(info);
 
         IOMX::buffer_id bufferId;
         err = mOMXNode->useBuffer(kPortIndexOutput, graphicBuffer, &bufferId);
@@ -1285,7 +1287,7 @@
             break;
         }
 
-        mBuffers[kPortIndexOutput].editItemAt(i).mBufferID = bufferId;
+        mBuffers[kPortIndexOutput][i].mBufferID = bufferId;
 
         ALOGV("[%s] Registered graphic buffer with ID %u (pointer = %p)",
              mComponentName.c_str(),
@@ -1307,7 +1309,7 @@
     }
 
     for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
-        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
+        BufferInfo *info = &mBuffers[kPortIndexOutput][i];
         if (info->mStatus == BufferInfo::OWNED_BY_US) {
             status_t error = cancelBufferToNativeWindow(info);
             if (err == 0) {
@@ -1336,6 +1338,7 @@
     ALOGV("[%s] Allocating %u meta buffers on output port",
          mComponentName.c_str(), bufferCount);
 
+    mBuffers[kPortIndexOutput].reserve(bufferCount);
     for (OMX_U32 i = 0; i < bufferCount; i++) {
         BufferInfo info;
         info.mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
@@ -1353,7 +1356,7 @@
         info.mCodecData = info.mData;
 
         err = mOMXNode->useBuffer(kPortIndexOutput, OMXBuffer::sPreset, &info.mBufferID);
-        mBuffers[kPortIndexOutput].push(info);
+        mBuffers[kPortIndexOutput].push_back(info);
 
         ALOGV("[%s] allocated meta buffer with ID %u",
                 mComponentName.c_str(), info.mBufferID);
@@ -1462,7 +1465,7 @@
             it != done.cend(); ++it) {
         ssize_t index = it->getIndex();
         if (index >= 0 && (size_t)index < mBuffers[kPortIndexOutput].size()) {
-            mBuffers[kPortIndexOutput].editItemAt(index).mRenderInfo = NULL;
+            mBuffers[kPortIndexOutput][index].mRenderInfo = NULL;
         } else if (index >= 0) {
             // THIS SHOULD NEVER HAPPEN
             ALOGE("invalid index %zd in %zu", index, mBuffers[kPortIndexOutput].size());
@@ -1502,7 +1505,7 @@
         bool stale = false;
         for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
             i--;
-            BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
+            BufferInfo *info = &mBuffers[kPortIndexOutput][i];
 
             if (info->mGraphicBuffer != NULL &&
                     info->mGraphicBuffer->handle == buf->handle) {
@@ -1550,8 +1553,7 @@
     BufferInfo *oldest = NULL;
     for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
         i--;
-        BufferInfo *info =
-            &mBuffers[kPortIndexOutput].editItemAt(i);
+        BufferInfo *info = &mBuffers[kPortIndexOutput][i];
         if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
             (oldest == NULL ||
              // avoid potential issues from counter rolling over
@@ -1608,8 +1610,7 @@
     status_t err = OK;
     for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
         i--;
-        BufferInfo *info =
-            &mBuffers[kPortIndexOutput].editItemAt(i);
+        BufferInfo *info = &mBuffers[kPortIndexOutput][i];
 
         // At this time some buffers may still be with the component
         // or being drained.
@@ -1626,7 +1627,7 @@
 }
 
 status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
-    BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+    BufferInfo *info = &mBuffers[portIndex][i];
     status_t err = OK;
 
     // there should not be any fences in the metadata
@@ -1666,14 +1667,14 @@
     }
 
     // remove buffer even if mOMXNode->freeBuffer fails
-    mBuffers[portIndex].removeAt(i);
+    mBuffers[portIndex].erase(mBuffers[portIndex].begin() + i);
     return err;
 }
 
 ACodec::BufferInfo *ACodec::findBufferByID(
         uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
-        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+        BufferInfo *info = &mBuffers[portIndex][i];
 
         if (info->mBufferID == bufferID) {
             if (index != NULL) {
@@ -5102,7 +5103,7 @@
     size_t n = 0;
 
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
-        const BufferInfo &info = mBuffers[portIndex].itemAt(i);
+        const BufferInfo &info = mBuffers[portIndex][i];
 
         if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
             ++n;
@@ -5116,7 +5117,7 @@
     size_t n = 0;
 
     for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
-        const BufferInfo &info = mBuffers[kPortIndexOutput].itemAt(i);
+        const BufferInfo &info = mBuffers[kPortIndexOutput][i];
 
         if (info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
             ++n;
@@ -5143,7 +5144,7 @@
 bool ACodec::allYourBuffersAreBelongToUs(
         OMX_U32 portIndex) {
     for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
-        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+        BufferInfo *info = &mBuffers[portIndex][i];
 
         if (info->mStatus != BufferInfo::OWNED_BY_US
                 && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
@@ -5167,12 +5168,11 @@
 }
 
 void ACodec::processDeferredMessages() {
-    List<sp<AMessage> > queue = mDeferredQueue;
+    std::list<sp<AMessage>> queue = mDeferredQueue;
     mDeferredQueue.clear();
 
-    List<sp<AMessage> >::iterator it = queue.begin();
-    while (it != queue.end()) {
-        onMessageReceived(*it++);
+    for(const sp<AMessage> &msg : queue) {
+        onMessageReceived(msg);
     }
 }
 
@@ -5928,19 +5928,17 @@
 
         case ACodec::kWhatSetSurface:
         {
+            sp<AReplyToken> replyID;
+            CHECK(msg->senderAwaitsResponse(&replyID));
+
             sp<RefBase> obj;
             CHECK(msg->findObject("surface", &obj));
 
             status_t err = mCodec->handleSetSurface(static_cast<Surface *>(obj.get()));
 
-            sp<AReplyToken> replyID;
-            if (msg->senderAwaitsResponse(&replyID)) {
-                sp<AMessage> response = new AMessage;
-                response->setInt32("err", err);
-                response->postReply(replyID);
-            } else if (err != OK) {
-                mCodec->signalError(OMX_ErrorUndefined, err);
-            }
+            sp<AMessage> response = new AMessage;
+            response->setInt32("err", err);
+            response->postReply(replyID);
             break;
         }
 
@@ -6483,7 +6481,7 @@
     BufferInfo *eligible = NULL;
 
     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
-        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput][i];
 
 #if 0
         if (info->mStatus == BufferInfo::OWNED_BY_UPSTREAM) {
@@ -6753,6 +6751,8 @@
         info->checkReadFence("onOutputBufferDrained before queueBuffer");
         err = mCodec->mNativeWindow->queueBuffer(
                     mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), info->mFenceFd);
+        // TODO(b/266211548): Poll the native window for rendered buffers, since when queueing
+        // buffers, the frame event history delta is retrieved.
         info->mFenceFd = -1;
         if (err == OK) {
             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
@@ -7515,7 +7515,7 @@
     // submit as many buffers as there are input buffers with the codec
     // in case we are in port reconfiguring
     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); ++i) {
-        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput][i];
 
         if (info->mStatus == BufferInfo::OWNED_BY_COMPONENT) {
             if (mCodec->submitOutputMetadataBuffer() != OK)
@@ -7533,7 +7533,7 @@
 void ACodec::ExecutingState::submitRegularOutputBuffers() {
     bool failed = false;
     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
-        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
+        BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput][i];
 
         if (mCodec->mNativeWindow != NULL) {
             if (info->mStatus != BufferInfo::OWNED_BY_US
@@ -7590,7 +7590,7 @@
     }
 
     for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
-        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
+        BufferInfo *info = &mCodec->mBuffers[kPortIndexInput][i];
         if (info->mStatus == BufferInfo::OWNED_BY_US) {
             postFillThisBuffer(info);
         }
@@ -8529,17 +8529,11 @@
 
         case kWhatSetSurface:
         {
-            ALOGV("[%s] Deferring setSurface", mCodec->mComponentName.c_str());
-
-            sp<AReplyToken> replyID;
-            CHECK(msg->senderAwaitsResponse(&replyID));
+            ALOGD("[%s] Deferring setSurface from OutputPortSettingsChangedState",
+                  mCodec->mComponentName.c_str());
 
             mCodec->deferMessage(msg);
 
-            sp<AMessage> response = new AMessage;
-            response->setInt32("err", OK);
-            response->postReply(replyID);
-
             handled = true;
             break;
         }
@@ -8594,7 +8588,7 @@
                 ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
 
                 status_t err = OK;
-                if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
+                if (!mCodec->mBuffers[kPortIndexOutput].empty()) {
                     ALOGE("disabled port should be empty, but has %zu buffers",
                             mCodec->mBuffers[kPortIndexOutput].size());
                     err = FAILED_TRANSACTION;
diff --git a/media/libstagefright/ACodecBufferChannel.cpp b/media/libstagefright/ACodecBufferChannel.cpp
index 88b15ae..529ae97 100644
--- a/media/libstagefright/ACodecBufferChannel.cpp
+++ b/media/libstagefright/ACodecBufferChannel.cpp
@@ -477,6 +477,10 @@
     return OK;
 }
 
+void ACodecBufferChannel::pollForRenderedBuffers() {
+    // TODO(b/266211548): Poll the native window for rendered buffers.
+}
+
 status_t ACodecBufferChannel::discardBuffer(const sp<MediaCodecBuffer> &buffer) {
     std::shared_ptr<const std::vector<const BufferInfo>> array(
             std::atomic_load(&mInputBuffers));
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 10baec4..32e40c3 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -33,75 +33,6 @@
     },
 }
 
-cc_library_static {
-    name: "libstagefright_esds",
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.media",
-    ],
-    min_sdk_version: "29",
-
-    srcs: ["ESDS.cpp"],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    sanitize: {
-        misc_undefined: [
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-    shared_libs: [
-        "libstagefright_foundation",
-        "libutils"
-    ],
-    host_supported: true,
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-}
-
-cc_library_static {
-    name: "libstagefright_metadatautils",
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.media",
-    ],
-    min_sdk_version: "29",
-
-    srcs: ["MetaDataUtils.cpp"],
-
-    cflags: [
-        "-Werror",
-        "-Wall",
-    ],
-    sanitize: {
-        misc_undefined: [
-            "signed-integer-overflow",
-        ],
-        cfi: true,
-    },
-
-    header_libs: [
-        "libaudioclient_headers",
-        "libstagefright_foundation_headers",
-        "media_ndk_headers",
-    ],
-
-    host_supported: true,
-    target: {
-        darwin: {
-            enabled: false,
-        },
-    },
-
-    export_include_dirs: ["include"],
-}
-
 cc_library_shared {
     name: "libstagefright_codecbase",
 
@@ -166,6 +97,10 @@
         "liblog",
     ],
 
+    static_libs: [
+        "libstagefright_esds",
+    ],
+
     export_include_dirs: [
         "include",
     ],
@@ -220,6 +155,7 @@
         "libEGL",
         "libGLESv1_CM",
         "libGLESv2",
+        "libvulkan",
         "libgui",
         "liblog",
         "libprocessgroup",
@@ -365,7 +301,6 @@
         "libstagefright_codecbase",
         "libstagefright_foundation",
         "libstagefright_omx_utils",
-        "libRScpp",
         "libhidlallocatorutils",
         "libhidlbase",
         "libhidlmemory",
@@ -382,11 +317,9 @@
         "libstagefright_esds",
         "libstagefright_color_conversion",
         "libyuv_static",
-        "libstagefright_mediafilter",
         "libstagefright_webm",
         "libstagefright_timedtext",
         "libogg",
-        "libwebm",
         "libstagefright_id3",
         "framework-permission-aidl-cpp",
         "libmediandk_format",
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index bfe8538..584dad6 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -522,7 +522,7 @@
 }
 
 status_t AudioSource::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo>* activeMicrophones) {
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
     if (mRecord != 0) {
         return mRecord->getActiveMicrophones(activeMicrophones);
     }
diff --git a/media/libstagefright/DataConverter.cpp b/media/libstagefright/DataConverter.cpp
index 52be054..b53ac77 100644
--- a/media/libstagefright/DataConverter.cpp
+++ b/media/libstagefright/DataConverter.cpp
@@ -24,6 +24,10 @@
 #include <media/MediaCodecBuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
+#include <system/audio.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/format.h>
+
 
 namespace android {
 
@@ -81,12 +85,38 @@
     return numSamples * mTargetSampleSize;
 }
 
+static audio_format_t getAudioFormat(AudioEncoding e) {
+    audio_format_t format = AUDIO_FORMAT_INVALID;
+    switch (e) {
+        case kAudioEncodingPcm16bit:
+            format = AUDIO_FORMAT_PCM_16_BIT;
+            break;
+        case kAudioEncodingPcm8bit:
+            format = AUDIO_FORMAT_PCM_8_BIT;
+            break;
+        case kAudioEncodingPcmFloat:
+            format = AUDIO_FORMAT_PCM_FLOAT;
+            break;
+       case kAudioEncodingPcm24bitPacked:
+            format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+            break;
+       case kAudioEncodingPcm32bit:
+            format = AUDIO_FORMAT_PCM_32_BIT;
+            break;
+        default:
+            ALOGE("Invalid AudioEncoding %d", e);
+        }
+        return format;
+}
 
 static size_t getAudioSampleSize(AudioEncoding e) {
     switch (e) {
-        case kAudioEncodingPcm16bit: return 2;
-        case kAudioEncodingPcm8bit:  return 1;
-        case kAudioEncodingPcmFloat: return 4;
+        case kAudioEncodingPcm16bit:
+        case kAudioEncodingPcm8bit:
+        case kAudioEncodingPcmFloat:
+        case kAudioEncodingPcm24bitPacked:
+        case kAudioEncodingPcm32bit:
+            return audio_bytes_per_sample(getAudioFormat(e));
         default: return 0;
     }
 }
@@ -116,7 +146,15 @@
     } else if (mTo == kAudioEncodingPcmFloat && mFrom == kAudioEncodingPcm16bit) {
         memcpy_to_float_from_i16((float*)tgt->base(), (const int16_t*)src->data(), src->size() / 2);
     } else {
-        return INVALID_OPERATION;
+        audio_format_t srcFormat = getAudioFormat(mFrom);
+        audio_format_t dstFormat = getAudioFormat(mTo);
+
+        if ((srcFormat == AUDIO_FORMAT_INVALID) || (dstFormat == AUDIO_FORMAT_INVALID))
+            return INVALID_OPERATION;
+
+        size_t frames = src->size() / audio_bytes_per_sample(srcFormat);
+        memcpy_by_audio_format((void*)tgt->base(), dstFormat, (void*)src->data(),
+                srcFormat, frames);
     }
     return OK;
 }
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 344456c..42815b3 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -352,6 +352,10 @@
     status_t err = OK;
     bool done = false;
     size_t retriesLeft = kRetryCount;
+    if (!mDecoder) {
+        ALOGE("decoder is not initialized");
+        return NO_INIT;
+    }
     do {
         size_t index;
         int64_t ptsUs = 0LL;
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 34b840e..fbc684b 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -30,7 +30,7 @@
 #include <media/stagefright/MetaData.h>
 #include <arpa/inet.h>
 
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
 
 namespace android {
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 63d3180..386b790 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -51,7 +51,7 @@
 #include <media/mediarecorder.h>
 #include <cutils/properties.h>
 
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
 #include "include/HevcUtils.h"
 
 #ifndef __predict_false
diff --git a/media/libstagefright/MediaAppender.cpp b/media/libstagefright/MediaAppender.cpp
index 21dcfa1..2d9c651 100644
--- a/media/libstagefright/MediaAppender.cpp
+++ b/media/libstagefright/MediaAppender.cpp
@@ -308,7 +308,11 @@
         ALOGE("MediaAppender::start() is called in invalid state %d", mState);
         return INVALID_OPERATION;
     }
-    mMuxer = new (std::nothrow) MediaMuxer(mFd, mFormat);
+    mMuxer = MediaMuxer::create(mFd, mFormat);
+    if (mMuxer == nullptr) {
+        ALOGE("MediaMuxer::create failed");
+        return INVALID_OPERATION;
+    }
     for (const auto& n : mFmtIndexMap) {
         ssize_t muxIndex = mMuxer->addTrack(n.second);
         if (muxIndex < 0) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 3044c20..9b8cc5e 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -75,7 +75,6 @@
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaFilter.h>
 #include <media/stagefright/OMXClient.h>
 #include <media/stagefright/PersistentSurface.h>
 #include <media/stagefright/SurfaceUtils.h>
@@ -89,6 +88,7 @@
 using aidl::android::media::BnResourceManagerClient;
 using aidl::android::media::IResourceManagerClient;
 using aidl::android::media::IResourceManagerService;
+using aidl::android::media::ClientInfoParcel;
 
 // key for media statistics
 static const char *kCodecKeyName = "codec";
@@ -210,8 +210,8 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 struct ResourceManagerClient : public BnResourceManagerClient {
-    explicit ResourceManagerClient(MediaCodec* codec, int32_t pid) :
-            mMediaCodec(codec), mPid(pid) {}
+    explicit ResourceManagerClient(MediaCodec* codec, int32_t pid, int32_t uid) :
+            mMediaCodec(codec), mPid(pid), mUid(uid) {}
 
     Status reclaimResource(bool* _aidl_return) override {
         sp<MediaCodec> codec = mMediaCodec.promote();
@@ -223,7 +223,10 @@
             if (service == nullptr) {
                 ALOGW("MediaCodec::ResourceManagerClient unable to find ResourceManagerService");
             }
-            service->removeClient(mPid, getId(this));
+            ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                .uid = static_cast<int32_t>(mUid),
+                                .id = getId(this)};
+            service->removeClient(clientInfo);
             *_aidl_return = true;
             return Status::ok();
         }
@@ -261,6 +264,7 @@
 private:
     wp<MediaCodec> mMediaCodec;
     int32_t mPid;
+    int32_t mUid;
 
     DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
 };
@@ -286,10 +290,15 @@
     void markClientForPendingRemoval();
     bool reclaimResource(const std::vector<MediaResourceParcel> &resources);
 
+    inline void setCodecName(const char* name) {
+        mCodecName = name;
+    }
+
 private:
     Mutex mLock;
     pid_t mPid;
     uid_t mUid;
+    std::string mCodecName;
     std::shared_ptr<IResourceManagerService> mService;
     std::shared_ptr<IResourceManagerClient> mClient;
     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
@@ -396,7 +405,11 @@
     if (mService == nullptr) {
         return;
     }
-    mService->addResource(mPid, mUid, getId(mClient), mClient, resources);
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                .uid = static_cast<int32_t>(mUid),
+                                .id = getId(mClient),
+                                .name = mCodecName};
+    mService->addResource(clientInfo, mClient, resources);
 }
 
 void MediaCodec::ResourceManagerServiceProxy::removeResource(
@@ -408,7 +421,11 @@
     if (mService == nullptr) {
         return;
     }
-    mService->removeResource(mPid, getId(mClient), resources);
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                .uid = static_cast<int32_t>(mUid),
+                                .id = getId(mClient),
+                                .name = mCodecName};
+    mService->removeResource(clientInfo, resources);
 }
 
 void MediaCodec::ResourceManagerServiceProxy::removeClient() {
@@ -416,7 +433,11 @@
     if (mService == nullptr) {
         return;
     }
-    mService->removeClient(mPid, getId(mClient));
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                .uid = static_cast<int32_t>(mUid),
+                                .id = getId(mClient),
+                                .name = mCodecName};
+    mService->removeClient(clientInfo);
 }
 
 void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() {
@@ -424,7 +445,11 @@
     if (mService == nullptr) {
         return;
     }
-    mService->markClientForPendingRemoval(mPid, getId(mClient));
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                .uid = static_cast<int32_t>(mUid),
+                                .id = getId(mClient),
+                                .name = mCodecName};
+    mService->markClientForPendingRemoval(clientInfo);
 }
 
 bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
@@ -434,7 +459,11 @@
         return false;
     }
     bool success;
-    Status status = mService->reclaimResource(mPid, resources, &success);
+    ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                .uid = static_cast<int32_t>(mUid),
+                                .id = getId(mClient),
+                                .name = mCodecName};
+    Status status = mService->reclaimResource(clientInfo, resources, &success);
     return status.isOk() && success;
 }
 
@@ -504,6 +533,7 @@
     kWhatOutputFramesRendered = 'outR',
     kWhatOutputBuffersChanged = 'outC',
     kWhatFirstTunnelFrameReady = 'ftfR',
+    kWhatPollForRenderedBuffers = 'plrb',
 };
 
 class BufferCallback : public CodecBase::BufferCallback {
@@ -837,7 +867,7 @@
       mGetCodecBase(getCodecBase),
       mGetCodecInfo(getCodecInfo) {
     mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid,
-            ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid));
+            ::ndk::SharedRefBase::make<ResourceManagerClient>(this, pid, uid));
     if (!mGetCodecBase) {
         mGetCodecBase = [](const AString &name, const char *owner) {
             return GetCodecBase(name, owner);
@@ -1565,8 +1595,6 @@
     } else if (name.startsWithIgnoreCase("omx.")) {
         // at this time only ACodec specifies a mime type.
         return new ACodec;
-    } else if (name.startsWithIgnoreCase("android.filter.")) {
-        return new MediaFilter;
     } else {
         return NULL;
     }
@@ -1696,6 +1724,11 @@
 
     std::vector<MediaResourceParcel> resources;
     resources.push_back(MediaResource::CodecResource(secureCodec, toMediaResourceSubType(mDomain)));
+
+    // If the ComponentName is not set yet, use the name passed by the user.
+    if (mComponentName.empty()) {
+        mResourceManagerProxy->setCodecName(name.c_str());
+    }
     for (int i = 0; i <= kMaxRetry; ++i) {
         if (i > 0) {
             // Don't try to reclaim resource for the first time.
@@ -3459,6 +3492,8 @@
                     if (mComponentName.c_str()) {
                         mediametrics_setCString(mMetricsHandle, kCodecCodec,
                                                 mComponentName.c_str());
+                        // Update the codec name.
+                        mResourceManagerProxy->setCodecName(mComponentName.c_str());
                     }
 
                     const char *owner = mCodecInfo ? mCodecInfo->getOwnerName() : "";
@@ -3481,8 +3516,8 @@
                     MediaCodecInfo::Attributes attr = mCodecInfo
                             ? mCodecInfo->getAttributes()
                             : MediaCodecInfo::Attributes(0);
-                    if (!(attr & MediaCodecInfo::kFlagIsSoftwareOnly)) {
-                        // software codec is currently ignored.
+                    if (mDomain == DOMAIN_VIDEO || !(attr & MediaCodecInfo::kFlagIsSoftwareOnly)) {
+                        // software audio codecs are currently ignored.
                         mResourceManagerProxy->addResource(MediaResource::CodecResource(
                             mFlags & kFlagIsSecure, toMediaResourceSubType(mDomain)));
                     }
@@ -4610,6 +4645,14 @@
             break;
         }
 
+        case kWhatPollForRenderedBuffers:
+        {
+            if (isExecuting()) {
+                mBufferChannel->pollForRenderedBuffers();
+            }
+            break;
+        }
+
         case kWhatSignalEndOfInputStream:
         {
             if (!isExecuting() || !mHaveInputSurface) {
@@ -4841,7 +4884,7 @@
         // rendering.
         int32_t dataSpace;
         if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
-            ALOGD("[%s] setting dataspace on output surface to #%x",
+            ALOGD("[%s] setting dataspace on output surface to %#x",
                     mComponentName.c_str(), dataSpace);
             int err = native_window_set_buffers_data_space(
                     mSurface.get(), (android_dataspace)dataSpace);
@@ -5323,7 +5366,6 @@
 size_t MediaCodec::CreateFramesRenderedMessage(
         const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
     size_t index = 0;
-
     for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
             it != done.cend(); ++it) {
         if (it->getRenderTimeNs() < 0) {
@@ -5372,11 +5414,13 @@
         int64_t mediaTimeUs = -1;
         buffer->meta()->findInt64("timeUs", &mediaTimeUs);
 
+        bool noRenderTime = false;
         int64_t renderTimeNs = 0;
         if (!msg->findInt64("timestampNs", &renderTimeNs)) {
             // use media timestamp if client did not request a specific render timestamp
             ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
             renderTimeNs = mediaTimeUs * 1000;
+            noRenderTime = true;
         }
 
         if (mSoftRenderer != NULL) {
@@ -5394,6 +5438,29 @@
                 }
             }
         }
+
+        // If rendering to the screen, then schedule a time in the future to poll to see if this
+        // frame was ever rendered to seed onFrameRendered callbacks.
+        if (mIsSurfaceToScreen) {
+            // can't initialize this in the constructor because the Looper parent class needs to be
+            // initialized first
+            if (mMsgPollForRenderedBuffers == nullptr) {
+                mMsgPollForRenderedBuffers = new AMessage(kWhatPollForRenderedBuffers, this);
+            }
+            // Schedule the poll to occur 100ms after the render time - should be safe for
+            // determining if the frame was ever rendered. If no render time was specified, the
+            // presentation timestamp is used instead, which almost certainly occurs in the past,
+            // since it's almost always a zero-based offset from the start of the stream. In these
+            // scenarios, we expect the frame to be rendered with no delay.
+            int64_t delayUs = noRenderTime ? 0 : renderTimeNs / 1000 - ALooper::GetNowUs();
+            delayUs += 100 * 1000; /* 100ms in microseconds */
+            status_t err =
+                    mMsgPollForRenderedBuffers->postUnique(/* token= */ mMsgPollForRenderedBuffers,
+                                                           delayUs);
+            if (err != OK) {
+                ALOGE("unexpected failure to post pollForRenderedBuffers: %d", err);
+            }
+        }
         status_t err = mBufferChannel->renderOutputBuffer(buffer, renderTimeNs);
 
         if (err == NO_INIT) {
@@ -5413,7 +5480,7 @@
 MediaCodec::BufferInfo *MediaCodec::peekNextPortBuffer(int32_t portIndex) {
     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
 
-    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
+    std::list<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
 
     if (availBuffers->empty()) {
         return nullptr;
@@ -5430,7 +5497,7 @@
         return -EAGAIN;
     }
 
-    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
+    std::list<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
     size_t index = *availBuffers->begin();
     CHECK_EQ(info, &mPortBuffers[portIndex][index]);
     availBuffers->erase(availBuffers->begin());
@@ -5635,6 +5702,9 @@
 }
 
 status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
+    if (mState == UNINITIALIZED || mState == INITIALIZING) {
+        return NO_INIT;
+    }
     updateLowLatency(params);
     mapFormat(mComponentName, params, nullptr, false);
     updateTunnelPeek(params);
diff --git a/media/libstagefright/MediaMuxer.cpp b/media/libstagefright/MediaMuxer.cpp
index a946f71..9f590e5 100644
--- a/media/libstagefright/MediaMuxer.cpp
+++ b/media/libstagefright/MediaMuxer.cpp
@@ -46,6 +46,30 @@
            format == MediaMuxer::OUTPUT_FORMAT_HEIF;
 }
 
+MediaMuxer* MediaMuxer::create(int fd, OutputFormat format) {
+    bool isInputValid = true;
+    if (isMp4Format(format)) {
+        isInputValid = MPEG4Writer::isFdOpenModeValid(fd);
+    } else if (format == OUTPUT_FORMAT_WEBM) {
+        isInputValid = WebmWriter::isFdOpenModeValid(fd);
+    } else if (format == OUTPUT_FORMAT_OGG) {
+        isInputValid = OggWriter::isFdOpenModeValid(fd);
+    } else {
+        ALOGE("MediaMuxer does not support output format %d", format);
+        return nullptr;
+    }
+    if (!isInputValid) {
+        ALOGE("File descriptor is not suitable for format %d", format);
+        return nullptr;
+    }
+
+    MediaMuxer *muxer = new (std::nothrow) MediaMuxer(fd, (MediaMuxer::OutputFormat)format);
+    if (muxer == nullptr) {
+        ALOGE("Failed to create writer object");
+    }
+    return muxer;
+}
+
 MediaMuxer::MediaMuxer(int fd, OutputFormat format)
     : mFormat(format),
       mState(UNINITIALIZED) {
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 2b45f2d..0536f2a 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -20,7 +20,7 @@
 
 #include <media/stagefright/NuMediaExtractor.h>
 
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
 
 #include <datasource/DataSourceFactory.h>
 #include <datasource/FileSource.h>
diff --git a/media/libstagefright/OWNERS b/media/libstagefright/OWNERS
index e67496e..f02e168 100644
--- a/media/libstagefright/OWNERS
+++ b/media/libstagefright/OWNERS
@@ -7,3 +7,5 @@
 
 # go/android-fwk-media-solutions for info on areas of ownership.
 include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
+
+per-file Camera*.cpp = file:/camera/OWNERS
diff --git a/media/libstagefright/OggWriter.cpp b/media/libstagefright/OggWriter.cpp
index 0f5e95e..cff37a3 100644
--- a/media/libstagefright/OggWriter.cpp
+++ b/media/libstagefright/OggWriter.cpp
@@ -96,6 +96,7 @@
         return ERROR_UNSUPPORTED;
     }
 
+    // NOLINTNEXTLINE(clang-analyzer-unix.MallocSizeof)
     mOs = (OggStreamState*) malloc(sizeof(ogg_stream_state));
     if (ogg_stream_init((ogg_stream_state*)mOs, rand()) == -1) {
         ALOGE("ogg stream init failed");
@@ -242,13 +243,15 @@
 
     mDone = true;
 
-    void* dummy;
-    pthread_join(mThread, &dummy);
+    status_t status = mSource->stop();
 
-    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
+    void *pthread_res;
+    pthread_join(mThread, &pthread_res);
+
+    status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(pthread_res));
     {
-        status_t status = mSource->stop();
-        if (err == OK && (status != OK && status != ERROR_END_OF_STREAM)) {
+        if (err == OK &&
+            (status != OK && status != ERROR_END_OF_STREAM)) {
             err = status;
         }
     }
diff --git a/media/libstagefright/SurfaceUtils.cpp b/media/libstagefright/SurfaceUtils.cpp
index f526e05..291b892 100644
--- a/media/libstagefright/SurfaceUtils.cpp
+++ b/media/libstagefright/SurfaceUtils.cpp
@@ -193,10 +193,38 @@
 
 status_t pushBlankBuffersToNativeWindow(ANativeWindow *nativeWindow /* nonnull */) {
     status_t err = NO_ERROR;
-    ANativeWindowBuffer* anb = NULL;
+    ANativeWindowBuffer* anb = nullptr;
     int numBufs = 0;
     int minUndequeuedBufs = 0;
 
+    auto handleError = [](ANativeWindow *nativeWindow, ANativeWindowBuffer* anb, status_t err)
+    {
+        if (anb != nullptr) {
+            nativeWindow->cancelBuffer(nativeWindow, anb, -1);
+            anb = nullptr;
+        }
+
+        // Clean up after success or error.
+        status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
+        if (err2 != NO_ERROR) {
+            ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)",
+                    strerror(-err2), -err2);
+            if (err == NO_ERROR) {
+                err = err2;
+            }
+        }
+
+        err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
+        if (err2 != NO_ERROR) {
+            ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
+            if (err == NO_ERROR) {
+                err = err2;
+            }
+        }
+
+        return err;
+    };
+
     // We need to reconnect to the ANativeWindow as a CPU client to ensure that
     // no frames get dropped by SurfaceFlinger assuming that these are video
     // frames.
@@ -217,7 +245,7 @@
             nativeWindow, 1, 1, HAL_PIXEL_FORMAT_RGBX_8888, 0, GRALLOC_USAGE_SW_WRITE_OFTEN,
             false /* reconnect */);
     if (err != NO_ERROR) {
-        goto error;
+        return handleError(nativeWindow, anb, err);
     }
 
     static_cast<Surface*>(nativeWindow)->getIGraphicBufferProducer()->allowAllocation(true);
@@ -232,14 +260,14 @@
     if (err != NO_ERROR) {
         ALOGE("error pushing blank frames: MIN_UNDEQUEUED_BUFFERS query "
                 "failed: %s (%d)", strerror(-err), -err);
-        goto error;
+        return handleError(nativeWindow, anb, err);
     }
 
     numBufs = minUndequeuedBufs + 1;
     err = native_window_set_buffer_count(nativeWindow, numBufs);
     if (err != NO_ERROR) {
         ALOGE("error pushing blank frames: set_buffer_count failed: %s (%d)", strerror(-err), -err);
-        goto error;
+        return handleError(nativeWindow, anb, err);
     }
 
     // We push numBufs + 1 buffers to ensure that we've drawn into the same
@@ -257,7 +285,7 @@
         sp<GraphicBuffer> buf(GraphicBuffer::from(anb));
 
         // Fill the buffer with the a 1x1 checkerboard pattern ;)
-        uint32_t *img = NULL;
+        uint32_t *img = nullptr;
         err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: lock failed: %s (%d)", strerror(-err), -err);
@@ -278,34 +306,10 @@
             break;
         }
 
-        anb = NULL;
+        anb = nullptr;
     }
 
-error:
-
-    if (anb != NULL) {
-        nativeWindow->cancelBuffer(nativeWindow, anb, -1);
-        anb = NULL;
-    }
-
-    // Clean up after success or error.
-    status_t err2 = native_window_api_disconnect(nativeWindow, NATIVE_WINDOW_API_CPU);
-    if (err2 != NO_ERROR) {
-        ALOGE("error pushing blank frames: api_disconnect failed: %s (%d)", strerror(-err2), -err2);
-        if (err == NO_ERROR) {
-            err = err2;
-        }
-    }
-
-    err2 = nativeWindowConnect(nativeWindow, "pushBlankBuffersToNativeWindow(err2)");
-    if (err2 != NO_ERROR) {
-        ALOGE("error pushing blank frames: api_connect failed: %s (%d)", strerror(-err), -err);
-        if (err == NO_ERROR) {
-            err = err2;
-        }
-    }
-
-    return err;
+    return handleError(nativeWindow, anb, err);
 }
 
 status_t nativeWindowConnect(ANativeWindow *surface, const char *reason) {
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index a443ed9..863177d 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -24,7 +24,7 @@
 #include <utility>
 #include <vector>
 
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
 #include "include/HevcUtils.h"
 
 #include <cutils/properties.h>
@@ -794,6 +794,12 @@
         { "thumbnail-height", kKeyThumbnailHeight },
         { "track-id", kKeyTrackID },
         { "valid-samples", kKeyValidSamples },
+        { "dvb-component-tag", kKeyDvbComponentTag},
+        { "dvb-audio-description", kKeyDvbAudioDescription},
+        { "dvb-teletext-magazine-number", kKeyDvbTeletextMagazineNumber},
+        { "dvb-teletext-page-number", kKeyDvbTeletextPageNumber},
+        { "profile", kKeyAudioProfile },
+        { "level", kKeyAudioLevel },
     }
 };
 
@@ -1002,6 +1008,26 @@
         msg->setInt32("is-sync-frame", 1);
     }
 
+    int32_t dvbComponentTag = 0;
+    if (meta->findInt32(kKeyDvbComponentTag, &dvbComponentTag)) {
+        msg->setInt32("dvb-component-tag", dvbComponentTag);
+    }
+
+    int32_t dvbAudioDescription = 0;
+    if (meta->findInt32(kKeyDvbAudioDescription, &dvbAudioDescription)) {
+        msg->setInt32("dvb-audio-description", dvbAudioDescription);
+    }
+
+    int32_t dvbTeletextMagazineNumber = 0;
+    if (meta->findInt32(kKeyDvbTeletextMagazineNumber, &dvbTeletextMagazineNumber)) {
+        msg->setInt32("dvb-teletext-magazine-number", dvbTeletextMagazineNumber);
+    }
+
+    int32_t dvbTeletextPageNumber = 0;
+    if (meta->findInt32(kKeyDvbTeletextPageNumber, &dvbTeletextPageNumber)) {
+        msg->setInt32("dvb-teletext-page-number", dvbTeletextPageNumber);
+    }
+
     const char *lang;
     if (meta->findCString(kKeyMediaLanguage, &lang)) {
         msg->setString("language", lang);
@@ -1788,6 +1814,26 @@
         meta->setInt32(kKeyMaxBitRate, maxBitrate);
     }
 
+    int32_t dvbComponentTag = 0;
+    if (msg->findInt32("dvb-component-tag", &dvbComponentTag) && dvbComponentTag > 0) {
+        meta->setInt32(kKeyDvbComponentTag, dvbComponentTag);
+    }
+
+    int32_t dvbAudioDescription = 0;
+    if (msg->findInt32("dvb-audio-description", &dvbAudioDescription)) {
+        meta->setInt32(kKeyDvbAudioDescription, dvbAudioDescription);
+    }
+
+    int32_t dvbTeletextMagazineNumber = 0;
+    if (msg->findInt32("dvb-teletext-magazine-number", &dvbTeletextMagazineNumber)) {
+        meta->setInt32(kKeyDvbTeletextMagazineNumber, dvbTeletextMagazineNumber);
+    }
+
+    int32_t dvbTeletextPageNumber = 0;
+    if (msg->findInt32("dvb-teletext-page-number", &dvbTeletextPageNumber)) {
+        meta->setInt32(kKeyDvbTeletextPageNumber, dvbTeletextPageNumber);
+    }
+
     AString lang;
     if (msg->findString("language", &lang)) {
         meta->setCString(kKeyMediaLanguage, lang.c_str());
@@ -1911,10 +1957,10 @@
         if (msg->findString("ts-schema", &tsSchema)) {
             unsigned int numLayers = 0;
             unsigned int numBLayers = 0;
-            char dummy;
+            char placeholder;
             int tags = sscanf(tsSchema.c_str(), "android.generic.%u%c%u%c",
-                    &numLayers, &dummy, &numBLayers, &dummy);
-            if ((tags == 1 || (tags == 3 && dummy == '+'))
+                    &numLayers, &placeholder, &numBLayers, &placeholder);
+            if ((tags == 1 || (tags == 3 && placeholder == '+'))
                     && numLayers > 0 && numLayers < UINT32_MAX - numBLayers
                     && numLayers + numBLayers <= INT32_MAX) {
                 meta->setInt32(kKeyTemporalLayerCount, numLayers + numBLayers);
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 4711315..2409315 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -441,7 +441,7 @@
                     ((dataSpace & ~HAL_DATASPACE_RANGE_MASK) | HAL_DATASPACE_RANGE_FULL);
         }
 
-        ALOGD("setting dataspace on output surface to #%x", dataSpace);
+        ALOGD("setting dataspace on output surface to %#x", dataSpace);
         if ((err = native_window_set_buffers_data_space(mNativeWindow.get(), dataSpace))) {
             ALOGW("failed to set dataspace on surface (%d)", err);
         }
diff --git a/media/libstagefright/colorconversion/fuzzer/Android.bp b/media/libstagefright/colorconversion/fuzzer/Android.bp
new file mode 100644
index 0000000..76b054a
--- /dev/null
+++ b/media/libstagefright/colorconversion/fuzzer/Android.bp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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_media_libstagefright_colorconversion_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: [
+        "frameworks_av_media_libstagefright_colorconversion_license",
+    ],
+}
+
+cc_defaults {
+    name: "libcolorconversion_fuzzer_defaults",
+    static_libs: [
+        "libyuv_static",
+        "libstagefright_color_conversion",
+        "libstagefright",
+        "liblog",
+    ],
+    header_libs: [
+        "libstagefright_headers",
+        "libgui_headers",
+    ],
+    shared_libs: [
+        "libui",
+        "libnativewindow",
+        "libstagefright_codecbase",
+        "libstagefright_foundation",
+        "libutils",
+        "libgui",
+        "libbinder",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
+
+cc_fuzz {
+    name: "color_conversion_fuzzer",
+    srcs: [
+        "color_conversion_fuzzer.cpp",
+    ],
+    defaults: [
+         "libcolorconversion_fuzzer_defaults",
+    ],
+}
diff --git a/media/libstagefright/colorconversion/fuzzer/README.md b/media/libstagefright/colorconversion/fuzzer/README.md
new file mode 100644
index 0000000..220f749
--- /dev/null
+++ b/media/libstagefright/colorconversion/fuzzer/README.md
@@ -0,0 +1,28 @@
+# Fuzzers for libstagefright_color_conversion
+
+## Table of contents
++ [color_conversion_fuzzer](#ColorConversion)
+
+
+# <a name="ColorConversion"></a> Fuzzer for  Colorconversion
+
+ColorConversion supports the following parameters:
+1. SrcColorFormatType (parameter name: "kSrcFormatType")
+2. DstColorFormatType (parameter name: "kDstFormatType")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`kSrcFormatType`| 0. `OMX_COLOR_FormatYUV420Planar`<br/>1. `OMX_COLOR_FormatYUV420Planar16`<br/>2. `OMX_COLOR_FormatYUV420SemiPlanar` <br/>3. `OMX_TI_COLOR_FormatYUV420PackedSemiPlanar` <br/>4.`OMX_COLOR_FormatCbYCrY`<br/>5.`OMX_QCOM_COLOR_FormatYVU420SemiPlanar`<br/>6.`COLOR_FormatYUVP010`|Value obtained from FuzzedDataProvider|
+|`kDstFormatType`| 0. `OMX_COLOR_Format16bitRGB565`<br/>1. `OMX_COLOR_Format32BitRGBA8888`<br/>2. `OMX_COLOR_Format32bitBGRA8888` <br/>3. `OMX_COLOR_Format16bitRGB565` <br/>4. `OMX_COLOR_Format32bitBGRA8888`<br/>5.`OMX_COLOR_FormatYUV444Y410`<br/>6. `COLOR_Format32bitABGR2101010`|Value obtained from FuzzedDataProvider|
+
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) color_conversion_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/color_conversion_fuzzer/color_conversion_fuzzer
+```
diff --git a/media/libstagefright/colorconversion/fuzzer/color_conversion_fuzzer.cpp b/media/libstagefright/colorconversion/fuzzer/color_conversion_fuzzer.cpp
new file mode 100644
index 0000000..7c2bfe5
--- /dev/null
+++ b/media/libstagefright/colorconversion/fuzzer/color_conversion_fuzzer.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <media/stagefright/ColorConverter.h>
+#include <media/stagefright/MediaCodecConstants.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <iostream>
+#include <vector>
+#include "fuzzer/FuzzedDataProvider.h"
+
+using namespace android;
+using ::android::sp;
+
+static constexpr int32_t kMinFrameSize = 2;
+static constexpr int32_t kMaxFrameSize = 8192;
+
+static constexpr int32_t kSrcFormatType[] = {OMX_COLOR_FormatYUV420Planar,
+                                             OMX_COLOR_FormatYUV420Planar16,
+                                             OMX_COLOR_FormatYUV420SemiPlanar,
+                                             OMX_TI_COLOR_FormatYUV420PackedSemiPlanar,
+                                             OMX_COLOR_FormatCbYCrY,
+                                             OMX_QCOM_COLOR_FormatYVU420SemiPlanar,
+                                             COLOR_FormatYUVP010};
+
+static constexpr int32_t kDstFormatType[] = {
+        OMX_COLOR_Format16bitRGB565, OMX_COLOR_Format32BitRGBA8888, OMX_COLOR_Format32bitBGRA8888,
+        OMX_COLOR_FormatYUV444Y410, COLOR_Format32bitABGR2101010};
+
+class ColorConversionFuzzer {
+  public:
+    ColorConversionFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+    int32_t getFrameSize(OMX_COLOR_FORMATTYPE colorFormat, int32_t stride, int32_t height);
+    bool isValidFormat(OMX_COLOR_FORMATTYPE srcFormat, OMX_COLOR_FORMATTYPE dstFormat);
+};
+
+int32_t ColorConversionFuzzer::getFrameSize(OMX_COLOR_FORMATTYPE colorFormat, int32_t stride,
+                                          int32_t height) {
+    int32_t frameSize;
+    switch ((int32_t)colorFormat) {
+        case OMX_COLOR_Format16bitRGB565: {
+            frameSize = 2 * stride * height;
+            break;
+        }
+        case OMX_COLOR_FormatYUV420Planar16:
+        case COLOR_FormatYUVP010:
+        case OMX_COLOR_FormatYUV444Y410: {
+            frameSize = 3 * stride * height;
+            break;
+        }
+        case OMX_COLOR_Format32bitBGRA8888:
+        case OMX_COLOR_Format32BitRGBA8888:
+        case COLOR_Format32bitABGR2101010: {
+            frameSize = 4 * stride * height;
+            break;
+        }
+        case OMX_COLOR_FormatYUV420Planar:
+        case OMX_COLOR_FormatYUV420SemiPlanar:
+        case OMX_COLOR_FormatCbYCrY:
+        case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+        case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
+        default: {
+            frameSize = stride * height + 2 * (((stride + 1) / 2) * ((height + 1) / 2));
+            break;
+        }
+    }
+    return frameSize;
+}
+
+void ColorConversionFuzzer::process() {
+    OMX_COLOR_FORMATTYPE srcColorFormat =
+            static_cast<OMX_COLOR_FORMATTYPE>(mFdp.PickValueInArray(kSrcFormatType));
+    OMX_COLOR_FORMATTYPE dstColorFormat =
+            static_cast<OMX_COLOR_FORMATTYPE>(mFdp.PickValueInArray(kDstFormatType));
+    std::unique_ptr<ColorConverter> converter(new ColorConverter(srcColorFormat, dstColorFormat));
+    if (converter->isValid()) {
+        int32_t srcLeft, srcTop, srcRight, srcBottom, width, height, stride;
+        width = mFdp.ConsumeIntegralInRange<int32_t>(kMinFrameSize, kMaxFrameSize);
+        height = mFdp.ConsumeIntegralInRange<int32_t>(kMinFrameSize, kMaxFrameSize);
+        stride = mFdp.ConsumeIntegralInRange<int32_t>(width, 2 * kMaxFrameSize);
+
+        srcLeft = mFdp.ConsumeIntegralInRange<int32_t>(0, width - 1);
+        srcTop = mFdp.ConsumeIntegralInRange<int32_t>(0, height - 1);
+        srcRight = mFdp.ConsumeIntegralInRange<int32_t>(srcLeft, width - 1);
+        srcBottom = mFdp.ConsumeIntegralInRange<int32_t>(srcTop, height - 1);
+
+        int32_t dstLeft, dstTop, dstRight, dstBottom;
+        dstLeft = mFdp.ConsumeIntegralInRange<int32_t>(0, width - 1);
+        dstTop = mFdp.ConsumeIntegralInRange<int32_t>(0, height - 1);
+        dstRight = mFdp.ConsumeIntegralInRange<int32_t>(dstLeft, width - 1);
+        dstBottom = mFdp.ConsumeIntegralInRange<int32_t>(dstTop, height - 1);
+
+        int32_t srcFrameSize = getFrameSize(srcColorFormat, stride, height);
+        int32_t dstFrameSize = getFrameSize(dstColorFormat, stride, height);
+        std::vector<uint8_t> srcFrame(srcFrameSize), dstFrame(dstFrameSize);
+        mFdp.ConsumeData(srcFrame.data(), srcFrameSize);
+        converter->convert(srcFrame.data(), width, height, stride, srcLeft, srcTop, srcRight,
+                           srcBottom, dstFrame.data(), width, height, stride, dstLeft, dstTop,
+                           dstRight, dstBottom);
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    ColorConversionFuzzer colorConversionFuzzer(data, size);
+    colorConversionFuzzer.process();
+    return 0;
+}
diff --git a/media/libstagefright/data/media_codecs_sw.xml b/media/libstagefright/data/media_codecs_sw.xml
index d7e2d18..b29c3b6 100644
--- a/media/libstagefright/data/media_codecs_sw.xml
+++ b/media/libstagefright/data/media_codecs_sw.xml
@@ -27,66 +27,77 @@
             <Limit name="channel-count" max="2" />
             <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
             <Limit name="bitrate" range="8000-320000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.amrnb.decoder" type="audio/3gpp">
             <Alias name="OMX.google.amrnb.decoder" />
             <Limit name="channel-count" max="1" />
             <Limit name="sample-rate" ranges="8000" />
             <Limit name="bitrate" range="4750-12200" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.amrwb.decoder" type="audio/amr-wb">
             <Alias name="OMX.google.amrwb.decoder" />
             <Limit name="channel-count" max="1" />
             <Limit name="sample-rate" ranges="16000" />
             <Limit name="bitrate" range="6600-23850" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.aac.decoder" type="audio/mp4a-latm">
             <Alias name="OMX.google.aac.decoder" />
             <Limit name="channel-count" max="8" />
             <Limit name="sample-rate" ranges="7350,8000,11025,12000,16000,22050,24000,32000,44100,48000" />
             <Limit name="bitrate" range="8000-960000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.g711.alaw.decoder" type="audio/g711-alaw">
             <Alias name="OMX.google.g711.alaw.decoder" />
             <Limit name="channel-count" max="6" />
             <Limit name="sample-rate" ranges="8000-48000" />
             <Limit name="bitrate" range="64000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.g711.mlaw.decoder" type="audio/g711-mlaw">
             <Alias name="OMX.google.g711.mlaw.decoder" />
             <Limit name="channel-count" max="6" />
             <Limit name="sample-rate" ranges="8000-48000" />
             <Limit name="bitrate" range="64000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.vorbis.decoder" type="audio/vorbis">
             <Alias name="OMX.google.vorbis.decoder" />
             <Limit name="channel-count" max="8" />
             <Limit name="sample-rate" ranges="8000-96000" />
             <Limit name="bitrate" range="32000-500000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.opus.decoder" type="audio/opus">
             <Alias name="OMX.google.opus.decoder" />
             <Limit name="channel-count" max="8" />
             <Limit name="sample-rate" ranges="8000,12000,16000,24000,48000" />
             <Limit name="bitrate" range="6000-510000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.raw.decoder" type="audio/raw">
             <Alias name="OMX.google.raw.decoder" />
             <Limit name="channel-count" max="8" />
-            <Limit name="sample-rate" ranges="8000-96000" />
+            <Limit name="sample-rate" ranges="8000-192000" />
             <Limit name="bitrate" range="1-10000000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.flac.decoder" type="audio/flac">
             <Alias name="OMX.google.flac.decoder" />
             <Limit name="channel-count" max="8" />
             <Limit name="sample-rate" ranges="1-655350" />
             <Limit name="bitrate" range="1-21000000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.gsm.decoder" type="audio/gsm" domain="telephony">
             <Alias name="OMX.google.gsm.decoder" />
             <Limit name="channel-count" max="1" />
             <Limit name="sample-rate" ranges="8000" />
             <Limit name="bitrate" range="13000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.mpeg4.decoder" type="video/mp4v-es">
             <Alias name="OMX.google.mpeg4.decoder" />
@@ -97,6 +108,7 @@
             <Limit name="blocks-per-second" range="1-432000" />
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.h263.decoder" type="video/3gpp">
             <Alias name="OMX.google.h263.decoder" />
@@ -106,6 +118,7 @@
             <Limit name="alignment" value="2x2" />
             <Limit name="bitrate" range="1-384000" />
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.avc.decoder" type="video/avc" variant="slow-cpu,!slow-cpu">
             <Alias name="OMX.google.h264.decoder" />
@@ -126,6 +139,7 @@
                 <Limit name="bitrate" range="1-40000000" />
             </Variant>
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.hevc.decoder" type="video/hevc" variant="slow-cpu,!slow-cpu">
             <Alias name="OMX.google.hevc.decoder" />
@@ -146,6 +160,7 @@
                 <Limit name="bitrate" range="1-5000000" />
             </Variant>
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.vp8.decoder" type="video/x-vnd.on2.vp8" variant="slow-cpu,!slow-cpu">
             <Alias name="OMX.google.vp8.decoder" />
@@ -163,6 +178,7 @@
                 <Limit name="bitrate" range="1-40000000" />
             </Variant>
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.vp9.decoder" type="video/x-vnd.on2.vp9" variant="slow-cpu,!slow-cpu">
             <Alias name="OMX.google.vp9.decoder" />
@@ -181,6 +197,7 @@
                 <Limit name="bitrate" range="1-5000000" />
             </Variant>
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.av1.decoder" type="video/av01" variant="!slow-cpu">
             <Limit name="size" min="2x2" max="2048x2048" />
@@ -190,6 +207,7 @@
             <Limit name="blocks-per-second" range="1-2073600" />
             <Limit name="bitrate" range="1-120000000" />
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.mpeg2.decoder" type="video/mpeg2" domain="tv">
             <Alias name="OMX.google.mpeg2.decoder" />
@@ -200,6 +218,7 @@
             <Limit name="blocks-per-second" range="1-244800" />
             <Limit name="bitrate" range="1-20000000" />
             <Feature name="adaptive-playback" />
+            <Attribute name="software-codec" />
         </MediaCodec>
     </Decoders>
     <Encoders>
@@ -209,6 +228,7 @@
             <Limit name="sample-rate" ranges="8000,11025,12000,16000,22050,24000,32000,44100,48000" />
             <!-- also may support 64000, 88200  and 96000 Hz -->
             <Limit name="bitrate" range="8000-960000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.amrnb.encoder" type="audio/3gpp">
             <Alias name="OMX.google.amrnb.encoder" />
@@ -216,6 +236,7 @@
             <Limit name="sample-rate" ranges="8000" />
             <Limit name="bitrate" range="4750-12200" />
             <Feature name="bitrate-modes" value="CBR" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.amrwb.encoder" type="audio/amr-wb">
             <Alias name="OMX.google.amrwb.encoder" />
@@ -223,6 +244,7 @@
             <Limit name="sample-rate" ranges="16000" />
             <Limit name="bitrate" range="6600-23850" />
             <Feature name="bitrate-modes" value="CBR" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.flac.encoder" type="audio/flac">
             <Alias name="OMX.google.flac.encoder" />
@@ -231,6 +253,7 @@
             <Limit name="bitrate" range="1-21000000" />
             <Limit name="complexity" range="0-8"  default="5" />
             <Feature name="bitrate-modes" value="CQ" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.opus.encoder" type="audio/opus">
             <Limit name="channel-count" max="2" />
@@ -238,6 +261,7 @@
             <Limit name="bitrate" range="500-512000" />
             <Limit name="complexity" range="0-10"  default="5" />
             <Feature name="bitrate-modes" value="CBR,VBR" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.h263.encoder" type="video/3gpp">
             <Alias name="OMX.google.h263.encoder" />
@@ -245,6 +269,7 @@
             <Limit name="size" min="176x144" max="176x144" />
             <Limit name="alignment" value="16x16" />
             <Limit name="bitrate" range="1-128000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.mpeg4.encoder" type="video/mp4v-es">
             <Alias name="OMX.google.mpeg4.encoder" />
@@ -254,6 +279,7 @@
             <Limit name="block-size" value="16x16" />
             <Limit name="blocks-per-second" range="12-1485" />
             <Limit name="bitrate" range="1-64000" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.avc.encoder" type="video/avc" variant="slow-cpu,!slow-cpu">
             <Alias name="OMX.google.h264.encoder" />
@@ -277,6 +303,7 @@
             <!-- Video Quality control -->
                     <!-- supports QP bounding with standard keys -->
             <Feature name="qp-bounds" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.vp8.encoder" type="video/x-vnd.on2.vp8" variant="slow-cpu,!slow-cpu">
             <Alias name="OMX.google.vp8.encoder" />
@@ -296,6 +323,7 @@
                 <Limit name="bitrate" range="1-20000000" />
             </Variant>
             <Feature name="bitrate-modes" value="VBR,CBR" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.hevc.encoder" type="video/hevc" variant="!slow-cpu">
             <!-- profiles and levels:  ProfileMain : MainTierLevel51 -->
@@ -309,6 +337,7 @@
             <Limit name="complexity" range="0-10"  default="0" />
             <Limit name="quality" range="0-100"  default="80" />
             <Feature name="bitrate-modes" value="VBR,CBR,CQ" />
+            <Attribute name="software-codec" />
         </MediaCodec>
         <MediaCodec name="c2.android.vp9.encoder" type="video/x-vnd.on2.vp9" variant="!slow-cpu">
             <Alias name="OMX.google.vp9.encoder" />
@@ -320,6 +349,7 @@
             <Limit name="block-count" range="1-3600" /> <!-- max 1280x720 -->
             <Limit name="bitrate" range="1-40000000" />
             <Feature name="bitrate-modes" value="VBR,CBR" />
+            <Attribute name="software-codec" />
         </MediaCodec>
     </Encoders>
 </MediaCodecs>
diff --git a/media/libstagefright/exports.lds b/media/libstagefright/exports.lds
index f5ddf1e..7fe6d6c 100644
--- a/media/libstagefright/exports.lds
+++ b/media/libstagefright/exports.lds
@@ -8,19 +8,19 @@
         _ZNK7android14ColorConverter*;
         _ZN7android16SoftwareRenderer*;
         ABGRToARGB;
-        ABGRToI420;
+        ABGRToI420*;
         ABGRToUVRow_Any_NEON*;
         ABGRToUVRow_C;
         ABGRToUVRow_NEON*;
         ABGRToYRow_Any_NEON*;
         ABGRToYRow_C;
         ABGRToYRow_NEON*;
-        Android420ToI420;
+        Android420ToI420*;
         ARGB1555ToARGB;
         ARGB1555ToARGBRow_Any_NEON*;
         ARGB1555ToARGBRow_C;
         ARGB1555ToARGBRow_NEON*;
-        ARGB1555ToI420;
+        ARGB1555ToI420*;
         ARGB1555ToUVRow_Any_NEON*;
         ARGB1555ToUVRow_C;
         ARGB1555ToUVRow_NEON*;
@@ -31,7 +31,7 @@
         ARGB4444ToARGBRow_Any_NEON*;
         ARGB4444ToARGBRow_C;
         ARGB4444ToARGBRow_NEON*;
-        ARGB4444ToI420;
+        ARGB4444ToI420*;
         ARGB4444ToUVRow_Any_NEON*;
         ARGB4444ToUVRow_C;
         ARGB4444ToUVRow_NEON*;
@@ -115,7 +115,7 @@
         ARGBToARGB4444Row_C;
         ARGBToARGB4444Row_NEON*;
         ARGBToBGRA;
-        ARGBToI420;
+        ARGBToI420*;
         ARGBToRAWRow_Any_NEON*;
         ARGBToRAWRow_C;
         ARGBToRAWRow_NEON*;
@@ -147,7 +147,7 @@
         ARGBUnattenuateRow_C;
         ArmCpuCaps*;
         BGRAToARGB;
-        BGRAToI420;
+        BGRAToI420*;
         BGRAToUVRow_Any_NEON*;
         BGRAToUVRow_C;
         BGRAToUVRow_NEON*;
@@ -156,9 +156,9 @@
         BGRAToYRow_NEON*;
         BlendPlane;
         BlendPlaneRow_C;
-        CanonicalFourCC;
+        CanonicalFourCC*;
         ComputeCumulativeSumRow_C;
-        ConvertFromI420;
+        ConvertFromI420*;
         CopyPlane;
         CopyPlane_16;
         CopyRow_16_C;
@@ -182,40 +182,40 @@
         HalfFloatRow_Any_NEON*;
         HalfFloatRow_C;
         HalfFloatRow_NEON*;
-        I400Copy;
+        I400Copy*;
         I400Mirror;
         I400ToARGB;
         I400ToARGBRow_Any_NEON*;
         I400ToARGBRow_C;
         I400ToARGBRow_NEON*;
         I400ToI400;
-        I400ToI420;
+        I400ToI420*;
         I420AlphaToABGR;
         I420AlphaToARGB;
         I420Blend;
-        I420Copy;
+        I420Copy*;
         I420Interpolate;
         I420Mirror;
         I420Rect;
-        I420Scale;
-        I420Scale_16;
+        I420Scale*;
+        I420Scale_16*;
         I420ToABGR;
         I420ToARGB;
         I420ToARGB1555;
         I420ToARGB4444;
         I420ToBGRA;
         I420ToI400;
-        I420ToI422;
-        I420ToI444;
-        I420ToNV12;
-        I420ToNV21;
+        I420ToI422*;
+        I420ToI444*;
+        I420ToNV12*;
+        I420ToNV21*;
         I420ToRAW;
         I420ToRGB24;
         I420ToRGB565;
         I420ToRGB565Dither;
         I420ToRGBA;
-        I420ToUYVY;
-        I420ToYUY2;
+        I420ToUYVY*;
+        I420ToYUY2*;
         I422AlphaToARGBRow_Any_NEON*;
         I422AlphaToARGBRow_C;
         I422AlphaToARGBRow_NEON*;
@@ -232,7 +232,7 @@
         I422ToARGBRow_C;
         I422ToARGBRow_NEON*;
         I422ToBGRA;
-        I422ToI420;
+        I422ToI420*;
         I422ToRGB24Row_Any_NEON*;
         I422ToRGB24Row_C;
         I422ToRGB24Row_NEON*;
@@ -244,11 +244,11 @@
         I422ToRGBARow_Any_NEON*;
         I422ToRGBARow_C;
         I422ToRGBARow_NEON*;
-        I422ToUYVY;
+        I422ToUYVY*;
         I422ToUYVYRow_Any_NEON*;
         I422ToUYVYRow_C;
         I422ToUYVYRow_NEON*;
-        I422ToYUY2;
+        I422ToYUY2*;
         I422ToYUY2Row_Any_NEON*;
         I422ToYUY2Row_C;
         I422ToYUY2Row_NEON*;
@@ -258,7 +258,7 @@
         I444ToARGBRow_Any_NEON*;
         I444ToARGBRow_C;
         I444ToARGBRow_NEON*;
-        I444ToI420;
+        I444ToI420*;
         InitCpuFlags*;
         InterpolatePlane;
         InterpolateRow_16_C;
@@ -280,8 +280,8 @@
         kYvuH709Constants;
         kYvuI601Constants;
         kYvuJPEGConstants;
-        M420ToARGB;
-        M420ToI420;
+        M420ToARGB*;
+        M420ToI420*;
         MaskCpuFlags*;
         MergeUVPlane;
         MergeUVRow_Any_NEON*;
@@ -297,7 +297,7 @@
         NV12ToARGBRow_Any_NEON*;
         NV12ToARGBRow_C;
         NV12ToARGBRow_NEON*;
-        NV12ToI420;
+        NV12ToI420*;
         NV12ToRGB565;
         NV12ToRGB565Row_Any_NEON*;
         NV12ToRGB565Row_C;
@@ -306,12 +306,12 @@
         NV21ToARGBRow_Any_NEON*;
         NV21ToARGBRow_C;
         NV21ToARGBRow_NEON*;
-        NV21ToI420;
+        NV21ToI420*;
         RAWToARGB;
         RAWToARGBRow_Any_NEON*;
         RAWToARGBRow_C;
         RAWToARGBRow_NEON*;
-        RAWToI420;
+        RAWToI420*;
         RAWToRGB24;
         RAWToRGB24Row_Any_NEON*;
         RAWToRGB24Row_C;
@@ -326,7 +326,7 @@
         RGB24ToARGBRow_Any_NEON*;
         RGB24ToARGBRow_C;
         RGB24ToARGBRow_NEON*;
-        RGB24ToI420;
+        RGB24ToI420*;
         RGB24ToUVRow_Any_NEON*;
         RGB24ToUVRow_C;
         RGB24ToUVRow_NEON*;
@@ -337,7 +337,7 @@
         RGB565ToARGBRow_Any_NEON*;
         RGB565ToARGBRow_C;
         RGB565ToARGBRow_NEON*;
-        RGB565ToI420;
+        RGB565ToI420*;
         RGB565ToUVRow_Any_NEON*;
         RGB565ToUVRow_C;
         RGB565ToUVRow_NEON*;
@@ -345,7 +345,7 @@
         RGB565ToYRow_C;
         RGB565ToYRow_NEON*;
         RGBAToARGB;
-        RGBAToI420;
+        RGBAToI420*;
         RGBAToUVRow_Any_NEON*;
         RGBAToUVRow_C;
         RGBAToUVRow_NEON*;
@@ -355,7 +355,7 @@
         RGBColorMatrix;
         RGBColorTable;
         RGBColorTableRow_C;
-        Scale;
+        Scale*;
         ScaleAddRow_16_C;
         ScaleAddRow_C;
         ScaleAddRows_NEON*;
@@ -395,12 +395,12 @@
         ScaleFilterCols_NEON*;
         ScaleFilterReduce;
         ScaleFilterRows_NEON*;
-        ScalePlane;
-        ScalePlane_16;
-        ScalePlaneBilinearDown;
-        ScalePlaneBilinearDown_16;
-        ScalePlaneBilinearUp;
-        ScalePlaneBilinearUp_16;
+        ScalePlane*;
+        ScalePlane_16*;
+        ScalePlaneBilinearDown*;
+        ScalePlaneBilinearDown_16*;
+        ScalePlaneBilinearUp*;
+        ScalePlaneBilinearUp_16*;
         ScalePlaneVertical;
         ScalePlaneVertical_16;
         ScaleRowDown2_16_C;
@@ -475,7 +475,7 @@
         UYVYToARGBRow_Any_NEON*;
         UYVYToARGBRow_C;
         UYVYToARGBRow_NEON*;
-        UYVYToI420;
+        UYVYToI420*;
         UYVYToI422;
         UYVYToNV12;
         UYVYToUV422Row_Any_NEON*;
@@ -491,7 +491,7 @@
         YUY2ToARGBRow_Any_NEON*;
         YUY2ToARGBRow_C;
         YUY2ToARGBRow_NEON*;
-        YUY2ToI420;
+        YUY2ToI420*;
         YUY2ToI422;
         YUY2ToNV12;
         YUY2ToUV422Row_Any_NEON*;
diff --git a/media/libstagefright/filters/Android.bp b/media/libstagefright/filters/Android.bp
deleted file mode 100644
index e6d59ad..0000000
--- a/media/libstagefright/filters/Android.bp
+++ /dev/null
@@ -1,52 +0,0 @@
-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_media_libstagefright_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
-}
-
-cc_library_static {
-    name: "libstagefright_mediafilter",
-
-    srcs: [
-        "ColorConvert.cpp",
-        "GraphicBufferListener.cpp",
-        "IntrinsicBlurFilter.cpp",
-        "MediaFilter.cpp",
-        "RSFilter.cpp",
-        "SaturationFilter.cpp",
-        "saturationARGB.rscript",
-        "SimpleFilter.cpp",
-        "ZeroFilter.cpp",
-    ],
-
-    export_include_dirs: [
-        "include",
-    ],
-
-    local_include_dirs: [
-        "include/filters",
-    ],
-
-    cflags: [
-        "-Wno-multichar",
-        "-Werror",
-        "-Wall",
-    ],
-
-    header_libs: [
-        "libmediadrm_headers",
-    ],
-
-    shared_libs: [
-        "libgui",
-        "libmedia",
-        "libhidlmemory",
-    ],
-
-    sanitize: {
-        cfi: true,
-    },
-}
diff --git a/media/libstagefright/filters/ColorConvert.cpp b/media/libstagefright/filters/ColorConvert.cpp
deleted file mode 100644
index a8d5dd2..0000000
--- a/media/libstagefright/filters/ColorConvert.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ColorConvert.h"
-
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
-namespace android {
-
-void YUVToRGB(
-        int32_t y, int32_t u, int32_t v,
-        int32_t* r, int32_t* g, int32_t* b) {
-    y -= 16;
-    u -= 128;
-    v -= 128;
-
-    *b = 1192 * y + 2066 * u;
-    *g = 1192 * y - 833 * v - 400 * u;
-    *r = 1192 * y + 1634 * v;
-
-    *r = min(262143, max(0, *r));
-    *g = min(262143, max(0, *g));
-    *b = min(262143, max(0, *b));
-
-    *r >>= 10;
-    *g >>= 10;
-    *b >>= 10;
-}
-
-void convertYUV420spToARGB(
-        uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
-        uint8_t *dest) {
-    const int32_t bytes_per_pixel = 2;
-
-    for (int32_t i = 0; i < height; i++) {
-        for (int32_t j = 0; j < width; j++) {
-            int32_t y = *(pY + i * width + j);
-            int32_t u = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
-            int32_t v = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
-
-            int32_t r, g, b;
-            YUVToRGB(y, u, v, &r, &g, &b);
-
-            *dest++ = 0xFF;
-            *dest++ = r;
-            *dest++ = g;
-            *dest++ = b;
-        }
-    }
-}
-
-void convertYUV420spToRGB888(
-        uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
-        uint8_t *dest) {
-    const int32_t bytes_per_pixel = 2;
-
-    for (int32_t i = 0; i < height; i++) {
-        for (int32_t j = 0; j < width; j++) {
-            int32_t y = *(pY + i * width + j);
-            int32_t u = *(pUV + (i/2) * width + bytes_per_pixel * (j/2));
-            int32_t v = *(pUV + (i/2) * width + bytes_per_pixel * (j/2) + 1);
-
-            int32_t r, g, b;
-            YUVToRGB(y, u, v, &r, &g, &b);
-
-            *dest++ = r;
-            *dest++ = g;
-            *dest++ = b;
-        }
-    }
-}
-
-// HACK - not even slightly optimized
-// TODO: remove when RGBA support is added to SoftwareRenderer
-void convertRGBAToARGB(
-        uint8_t *src, int32_t width, int32_t height, uint32_t stride,
-        uint8_t *dest) {
-    for (int32_t i = 0; i < height; ++i) {
-        for (int32_t j = 0; j < width; ++j) {
-            uint8_t r = *src++;
-            uint8_t g = *src++;
-            uint8_t b = *src++;
-            uint8_t a = *src++;
-            *dest++ = a;
-            *dest++ = r;
-            *dest++ = g;
-            *dest++ = b;
-        }
-        src += (stride - width) * 4;
-    }
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/GraphicBufferListener.cpp b/media/libstagefright/filters/GraphicBufferListener.cpp
deleted file mode 100644
index db061c1..0000000
--- a/media/libstagefright/filters/GraphicBufferListener.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "GraphicBufferListener"
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-#include <gui/BufferItem.h>
-#include <utils/String8.h>
-
-#include "GraphicBufferListener.h"
-
-namespace android {
-
-status_t GraphicBufferListener::init(
-        const sp<AMessage> &notify,
-        size_t bufferWidth, size_t bufferHeight, size_t bufferCount) {
-    mNotify = notify;
-
-    String8 name("GraphicBufferListener");
-    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-    mConsumer->setConsumerName(name);
-    mConsumer->setDefaultBufferSize(bufferWidth, bufferHeight);
-    mConsumer->setConsumerUsageBits(GRALLOC_USAGE_SW_READ_OFTEN);
-
-    status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
-    if (err != NO_ERROR) {
-        ALOGE("Unable to set BQ max acquired buffer count to %zu: %d",
-                bufferCount, err);
-        return err;
-    }
-
-    wp<BufferQueue::ConsumerListener> listener =
-        static_cast<BufferQueue::ConsumerListener*>(this);
-    sp<BufferQueue::ProxyConsumerListener> proxy =
-        new BufferQueue::ProxyConsumerListener(listener);
-
-    err = mConsumer->consumerConnect(proxy, false);
-    if (err != NO_ERROR) {
-        ALOGE("Error connecting to BufferQueue: %s (%d)",
-                strerror(-err), err);
-        return err;
-    }
-
-    ALOGV("init() successful.");
-
-    return OK;
-}
-
-void GraphicBufferListener::onFrameAvailable(const BufferItem& /* item */) {
-    ALOGV("onFrameAvailable() called");
-
-    {
-        Mutex::Autolock autoLock(mMutex);
-        mNumFramesAvailable++;
-    }
-
-    sp<AMessage> notify = mNotify->dup();
-    mNotify->setWhat(kWhatFrameAvailable);
-    mNotify->post();
-}
-
-void GraphicBufferListener::onBuffersReleased() {
-    ALOGV("onBuffersReleased() called");
-    // nothing to do
-}
-
-void GraphicBufferListener::onSidebandStreamChanged() {
-    ALOGW("GraphicBufferListener cannot consume sideband streams.");
-    // nothing to do
-}
-
-BufferItem GraphicBufferListener::getBufferItem() {
-    BufferItem item;
-
-    {
-        Mutex::Autolock autoLock(mMutex);
-        if (mNumFramesAvailable <= 0) {
-            ALOGE("getBuffer() called with no frames available");
-            return item;
-        }
-        mNumFramesAvailable--;
-    }
-
-    status_t err = mConsumer->acquireBuffer(&item, 0);
-    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
-        // shouldn't happen, since we track num frames available
-        ALOGE("frame was not available");
-        item.mSlot = -1;
-        return item;
-    } else if (err != OK) {
-        ALOGE("acquireBuffer returned err=%d", err);
-        item.mSlot = -1;
-        return item;
-    }
-
-    // Wait for it to become available.
-    err = item.mFence->waitForever("GraphicBufferListener::getBufferItem");
-    if (err != OK) {
-        ALOGW("failed to wait for buffer fence: %d", err);
-        // keep going
-    }
-
-    // If this is the first time we're seeing this buffer, add it to our
-    // slot table.
-    if (item.mGraphicBuffer != NULL) {
-        ALOGV("setting mBufferSlot %d", item.mSlot);
-        mBufferSlot[item.mSlot] = item.mGraphicBuffer;
-    }
-
-    return item;
-}
-
-sp<GraphicBuffer> GraphicBufferListener::getBuffer(BufferItem item) {
-    sp<GraphicBuffer> buf;
-    if (item.mSlot < 0 || item.mSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
-        ALOGE("getBuffer() received invalid BufferItem: mSlot==%d", item.mSlot);
-        return buf;
-    }
-
-    buf = mBufferSlot[item.mSlot];
-    CHECK(buf.get() != NULL);
-
-    return buf;
-}
-
-status_t GraphicBufferListener::releaseBuffer(BufferItem item) {
-    if (item.mSlot < 0 || item.mSlot >= BufferQueue::NUM_BUFFER_SLOTS) {
-        ALOGE("getBuffer() received invalid BufferItem: mSlot==%d", item.mSlot);
-        return ERROR_OUT_OF_RANGE;
-    }
-
-    mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
-            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE);
-
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/IntrinsicBlurFilter.cpp b/media/libstagefright/filters/IntrinsicBlurFilter.cpp
deleted file mode 100644
index e00afd9..0000000
--- a/media/libstagefright/filters/IntrinsicBlurFilter.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "IntrinsicBlurFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "IntrinsicBlurFilter.h"
-
-namespace android {
-
-status_t IntrinsicBlurFilter::configure(const sp<AMessage> &msg) {
-    status_t err = SimpleFilter::configure(msg);
-    if (err != OK) {
-        return err;
-    }
-
-    if (!msg->findString("cacheDir", &mCacheDir)) {
-        ALOGE("Failed to find cache directory in config message.");
-        return NAME_NOT_FOUND;
-    }
-
-    return OK;
-}
-
-status_t IntrinsicBlurFilter::start() {
-    // TODO: use a single RS context object for entire application
-    mRS = new RSC::RS();
-
-    if (!mRS->init(mCacheDir.c_str())) {
-        ALOGE("Failed to initialize RenderScript context.");
-        return NO_INIT;
-    }
-
-    // 32-bit elements for ARGB8888
-    RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
-    RSC::Type::Builder tb(mRS, e);
-    tb.setX(mWidth);
-    tb.setY(mHeight);
-    RSC::sp<const RSC::Type> t = tb.create();
-
-    mAllocIn = RSC::Allocation::createTyped(mRS, t);
-    mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
-    mBlur = RSC::ScriptIntrinsicBlur::create(mRS, e);
-    mBlur->setRadius(mBlurRadius);
-    mBlur->setInput(mAllocIn);
-
-    return OK;
-}
-
-void IntrinsicBlurFilter::reset() {
-    mBlur.clear();
-    mAllocOut.clear();
-    mAllocIn.clear();
-    mRS.clear();
-}
-
-status_t IntrinsicBlurFilter::setParameters(const sp<AMessage> &msg) {
-    sp<AMessage> params;
-    CHECK(msg->findMessage("params", &params));
-
-    float blurRadius;
-    if (params->findFloat("blur-radius", &blurRadius)) {
-        mBlurRadius = blurRadius;
-    }
-
-    return OK;
-}
-
-status_t IntrinsicBlurFilter::processBuffers(
-        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
-    mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
-    mBlur->forEach(mAllocOut);
-    mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
deleted file mode 100644
index c7baa73..0000000
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaFilter"
-
-#include <inttypes.h>
-#include <utils/Trace.h>
-
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include <media/stagefright/BufferProducerWrapper.h>
-#include <media/stagefright/MediaCodecConstants.h>
-#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MediaFilter.h>
-
-#include <media/MediaCodecBuffer.h>
-
-#include <gui/BufferItem.h>
-
-#include "ColorConvert.h"
-#include "GraphicBufferListener.h"
-#include "IntrinsicBlurFilter.h"
-#include "RSFilter.h"
-#include "SaturationFilter.h"
-#include "ZeroFilter.h"
-
-namespace android {
-
-class MediaFilter::BufferChannel : public BufferChannelBase {
-public:
-    BufferChannel(const sp<AMessage> &in, const sp<AMessage> &out)
-        : mInputBufferFilled(in), mOutputBufferDrained(out) {
-    }
-
-    ~BufferChannel() override = default;
-
-    // BufferChannelBase
-
-    status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override {
-        sp<AMessage> msg = mInputBufferFilled->dup();
-        msg->setObject("buffer", buffer);
-        msg->post();
-        return OK;
-    }
-
-    status_t queueSecureInputBuffer(
-            const sp<MediaCodecBuffer> &,
-            bool,
-            const uint8_t *,
-            const uint8_t *,
-            CryptoPlugin::Mode,
-            CryptoPlugin::Pattern,
-            const CryptoPlugin::SubSample *,
-            size_t,
-            AString *) override {
-        return INVALID_OPERATION;
-    }
-
-    status_t renderOutputBuffer(
-            const sp<MediaCodecBuffer> &buffer, int64_t /* timestampNs */) override {
-        sp<AMessage> msg = mOutputBufferDrained->dup();
-        msg->setObject("buffer", buffer);
-        msg->post();
-        return OK;
-    }
-
-    status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override {
-        if (FindBufferIndex(&mInputBuffers, buffer) >= 0) {
-            sp<AMessage> msg = mInputBufferFilled->dup();
-            msg->setObject("buffer", buffer);
-            msg->post();
-            return OK;
-        }
-        sp<AMessage> msg = mOutputBufferDrained->dup();
-        msg->setObject("buffer", buffer);
-        msg->post();
-        return OK;
-    }
-
-    void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
-        if (!array) {
-            return;
-        }
-        array->clear();
-        array->appendVector(mInputBuffers);
-    }
-
-    void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) {
-        if (!array) {
-            return;
-        }
-        array->clear();
-        array->appendVector(mOutputBuffers);
-    }
-
-    // For MediaFilter
-
-    void fillThisBuffer(const sp<MediaCodecBuffer> &buffer) {
-        ssize_t index = FindBufferIndex(&mInputBuffers, buffer);
-        mCallback->onInputBufferAvailable(index, buffer);
-    }
-
-    void drainThisBuffer(const sp<MediaCodecBuffer> &buffer, int flags) {
-        ssize_t index = FindBufferIndex(&mOutputBuffers, buffer);
-        buffer->meta()->setInt32("flags", flags);
-        mCallback->onOutputBufferAvailable(index, buffer);
-    }
-
-    template <class T>
-    void setInputBuffers(T begin, T end) {
-        mInputBuffers.clear();
-        for (T it = begin; it != end; ++it) {
-            mInputBuffers.push_back(it->mData);
-        }
-    }
-
-    template <class T>
-    void setOutputBuffers(T begin, T end) {
-        mOutputBuffers.clear();
-        for (T it = begin; it != end; ++it) {
-            mOutputBuffers.push_back(it->mData);
-        }
-    }
-
-private:
-    sp<AMessage> mInputBufferFilled;
-    sp<AMessage> mOutputBufferDrained;
-    Vector<sp<MediaCodecBuffer>> mInputBuffers;
-    Vector<sp<MediaCodecBuffer>> mOutputBuffers;
-
-    static ssize_t FindBufferIndex(
-            Vector<sp<MediaCodecBuffer>> *array, const sp<MediaCodecBuffer> &buffer) {
-        for (size_t i = 0; i < array->size(); ++i) {
-            if (array->itemAt(i) == buffer) {
-                return i;
-            }
-        }
-        return -1;
-    }
-};
-
-// parameter: number of input and output buffers
-static const size_t kBufferCountActual = 4;
-
-MediaFilter::MediaFilter()
-    : mState(UNINITIALIZED),
-      mGeneration(0),
-      mGraphicBufferListener(NULL) {
-}
-
-MediaFilter::~MediaFilter() {
-}
-
-//////////////////// PUBLIC FUNCTIONS //////////////////////////////////////////
-
-std::shared_ptr<BufferChannelBase> MediaFilter::getBufferChannel() {
-    if (!mBufferChannel) {
-        mBufferChannel = std::make_shared<BufferChannel>(
-                new AMessage(kWhatInputBufferFilled, this),
-                new AMessage(kWhatOutputBufferDrained, this));
-    }
-    return mBufferChannel;
-}
-
-void MediaFilter::initiateAllocateComponent(const sp<AMessage> &msg) {
-    msg->setWhat(kWhatAllocateComponent);
-    msg->setTarget(this);
-    msg->post();
-}
-
-void MediaFilter::initiateConfigureComponent(const sp<AMessage> &msg) {
-    msg->setWhat(kWhatConfigureComponent);
-    msg->setTarget(this);
-    msg->post();
-}
-
-void MediaFilter::initiateCreateInputSurface() {
-    (new AMessage(kWhatCreateInputSurface, this))->post();
-}
-
-void MediaFilter::initiateSetInputSurface(
-        const sp<PersistentSurface> & /* surface */) {
-    ALOGW("initiateSetInputSurface() unsupported");
-}
-
-void MediaFilter::initiateStart() {
-    (new AMessage(kWhatStart, this))->post();
-}
-
-void MediaFilter::initiateShutdown(bool keepComponentAllocated) {
-    sp<AMessage> msg = new AMessage(kWhatShutdown, this);
-    msg->setInt32("keepComponentAllocated", keepComponentAllocated);
-    msg->post();
-}
-
-void MediaFilter::signalFlush() {
-    (new AMessage(kWhatFlush, this))->post();
-}
-
-void MediaFilter::signalResume() {
-    (new AMessage(kWhatResume, this))->post();
-}
-
-// nothing to do
-void MediaFilter::signalRequestIDRFrame() {
-    return;
-}
-
-void MediaFilter::signalSetParameters(const sp<AMessage> &params) {
-    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
-    msg->setMessage("params", params);
-    msg->post();
-}
-
-void MediaFilter::signalEndOfInputStream() {
-    (new AMessage(kWhatSignalEndOfInputStream, this))->post();
-}
-
-void MediaFilter::onMessageReceived(const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatAllocateComponent:
-        {
-            onAllocateComponent(msg);
-            break;
-        }
-        case kWhatConfigureComponent:
-        {
-            onConfigureComponent(msg);
-            break;
-        }
-        case kWhatStart:
-        {
-            onStart();
-            break;
-        }
-        case kWhatProcessBuffers:
-        {
-            processBuffers();
-            break;
-        }
-        case kWhatInputBufferFilled:
-        {
-            onInputBufferFilled(msg);
-            break;
-        }
-        case kWhatOutputBufferDrained:
-        {
-            onOutputBufferDrained(msg);
-            break;
-        }
-        case kWhatShutdown:
-        {
-            onShutdown(msg);
-            break;
-        }
-        case kWhatFlush:
-        {
-            onFlush();
-            break;
-        }
-        case kWhatResume:
-        {
-            // nothing to do
-            break;
-        }
-        case kWhatSetParameters:
-        {
-            onSetParameters(msg);
-            break;
-        }
-        case kWhatCreateInputSurface:
-        {
-            onCreateInputSurface();
-            break;
-        }
-        case GraphicBufferListener::kWhatFrameAvailable:
-        {
-            onInputFrameAvailable();
-            break;
-        }
-        case kWhatSignalEndOfInputStream:
-        {
-            onSignalEndOfInputStream();
-            break;
-        }
-        default:
-        {
-            ALOGE("Message not handled:\n%s", msg->debugString().c_str());
-            break;
-        }
-    }
-}
-
-//////////////////// HELPER FUNCTIONS //////////////////////////////////////////
-
-void MediaFilter::signalProcessBuffers() {
-    (new AMessage(kWhatProcessBuffers, this))->post();
-}
-
-void MediaFilter::signalError(status_t error) {
-    mCallback->onError(error, ACTION_CODE_FATAL);
-}
-
-status_t MediaFilter::allocateBuffersOnPort(OMX_U32 portIndex) {
-    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
-    const bool isInput = portIndex == kPortIndexInput;
-    const size_t bufferSize = isInput ? mMaxInputSize : mMaxOutputSize;
-
-    CHECK(mBuffers[portIndex].isEmpty());
-
-    ALOGV("Allocating %zu buffers of size %zu on %s port",
-            kBufferCountActual, bufferSize,
-            isInput ? "input" : "output");
-
-    // trigger output format change
-    sp<AMessage> outputFormat = mOutputFormat->dup();
-    for (size_t i = 0; i < kBufferCountActual; ++i) {
-        BufferInfo info;
-        info.mStatus = BufferInfo::OWNED_BY_US;
-        info.mBufferID = i;
-        info.mGeneration = mGeneration;
-        info.mOutputFlags = 0;
-        info.mData = new MediaCodecBuffer(
-                isInput ? mInputFormat : outputFormat,
-                new ABuffer(bufferSize));
-        info.mData->meta()->setInt64("timeUs", 0);
-
-        mBuffers[portIndex].push_back(info);
-
-        if (!isInput) {
-            mAvailableOutputBuffers.push(
-                    &mBuffers[portIndex].editItemAt(i));
-        }
-    }
-    if (isInput) {
-        mBufferChannel->setInputBuffers(
-                mBuffers[portIndex].begin(), mBuffers[portIndex].end());
-    } else {
-        mBufferChannel->setOutputBuffers(
-                mBuffers[portIndex].begin(), mBuffers[portIndex].end());
-    }
-
-    return OK;
-}
-
-MediaFilter::BufferInfo* MediaFilter::findBuffer(
-        uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
-        ssize_t *index) {
-    for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
-        BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
-
-        if (info->mData == buffer) {
-            if (index != NULL) {
-                *index = i;
-            }
-            return info;
-        }
-    }
-
-    TRESPASS();
-
-    return NULL;
-}
-
-void MediaFilter::postFillThisBuffer(BufferInfo *info) {
-    ALOGV("postFillThisBuffer on buffer %d", info->mBufferID);
-    if (mPortEOS[kPortIndexInput]) {
-        return;
-    }
-
-    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
-
-    info->mGeneration = mGeneration;
-
-    info->mData->meta()->clear();
-
-    sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, this);
-    reply->setInt32("buffer-id", info->mBufferID);
-
-    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
-
-    mBufferChannel->fillThisBuffer(info->mData);
-}
-
-void MediaFilter::postDrainThisBuffer(BufferInfo *info) {
-    CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
-
-    info->mGeneration = mGeneration;
-
-    sp<AMessage> reply = new AMessage(kWhatOutputBufferDrained, this);
-    reply->setInt32("buffer-id", info->mBufferID);
-
-    mBufferChannel->drainThisBuffer(info->mData, info->mOutputFlags);
-
-    info->mStatus = BufferInfo::OWNED_BY_UPSTREAM;
-}
-
-void MediaFilter::postEOS() {
-    mCallback->onEos(ERROR_END_OF_STREAM);
-
-    ALOGV("Sent kWhatEOS.");
-}
-
-void MediaFilter::requestFillEmptyInput() {
-    if (mPortEOS[kPortIndexInput]) {
-        return;
-    }
-
-    for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
-        BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
-
-        if (info->mStatus == BufferInfo::OWNED_BY_US) {
-            postFillThisBuffer(info);
-        }
-    }
-}
-
-void MediaFilter::processBuffers() {
-    if (mAvailableInputBuffers.empty() || mAvailableOutputBuffers.empty()) {
-        ALOGV("Skipping process (buffers unavailable)");
-        return;
-    }
-
-    if (mPortEOS[kPortIndexOutput]) {
-        // TODO notify caller of queueInput error when it is supported
-        // in MediaCodec
-        ALOGW("Tried to process a buffer after EOS.");
-        return;
-    }
-
-    BufferInfo *inputInfo = mAvailableInputBuffers[0];
-    mAvailableInputBuffers.removeAt(0);
-    BufferInfo *outputInfo = mAvailableOutputBuffers[0];
-    mAvailableOutputBuffers.removeAt(0);
-
-    status_t err;
-    err = mFilter->processBuffers(inputInfo->mData, outputInfo->mData);
-    if (err != (status_t)OK) {
-        outputInfo->mData->meta()->setInt32("err", err);
-    }
-
-    int64_t timeUs;
-    CHECK(inputInfo->mData->meta()->findInt64("timeUs", &timeUs));
-    outputInfo->mData->meta()->setInt64("timeUs", timeUs);
-    outputInfo->mOutputFlags = 0;
-    int32_t eos = 0;
-    if (inputInfo->mData->meta()->findInt32("eos", &eos) && eos != 0) {
-        outputInfo->mOutputFlags |= BUFFER_FLAG_END_OF_STREAM;
-        mPortEOS[kPortIndexOutput] = true;
-        outputInfo->mData->meta()->setInt32("eos", eos);
-        postEOS();
-        ALOGV("Output stream saw EOS.");
-    }
-
-    ALOGV("Processed input buffer %u [%zu], output buffer %u [%zu]",
-                inputInfo->mBufferID, inputInfo->mData->size(),
-                outputInfo->mBufferID, outputInfo->mData->size());
-
-    if (mGraphicBufferListener != NULL) {
-        delete inputInfo;
-    } else {
-        postFillThisBuffer(inputInfo);
-    }
-    postDrainThisBuffer(outputInfo);
-
-    // prevent any corner case where buffers could get stuck in queue
-    signalProcessBuffers();
-}
-
-void MediaFilter::onAllocateComponent(const sp<AMessage> &msg) {
-    CHECK_EQ(mState, UNINITIALIZED);
-
-    CHECK(msg->findString("componentName", &mComponentName));
-    const char* name = mComponentName.c_str();
-    if (!strcasecmp(name, "android.filter.zerofilter")) {
-        mFilter = new ZeroFilter;
-    } else if (!strcasecmp(name, "android.filter.saturation")) {
-        mFilter = new SaturationFilter;
-    } else if (!strcasecmp(name, "android.filter.intrinsicblur")) {
-        mFilter = new IntrinsicBlurFilter;
-    } else if (!strcasecmp(name, "android.filter.RenderScript")) {
-        mFilter = new RSFilter;
-    } else {
-        ALOGE("Unrecognized filter name: %s", name);
-        signalError(NAME_NOT_FOUND);
-        return;
-    }
-
-    mCallback->onComponentAllocated(mComponentName.c_str());
-    mState = INITIALIZED;
-    ALOGV("Handled kWhatAllocateComponent.");
-}
-
-void MediaFilter::onConfigureComponent(const sp<AMessage> &msg) {
-    // TODO: generalize to allow audio filters as well as video
-
-    CHECK_EQ(mState, INITIALIZED);
-
-    // get params - at least mime, width & height
-    AString mime;
-    CHECK(msg->findString("mime", &mime));
-    if (strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_RAW)) {
-        ALOGE("Bad mime: %s", mime.c_str());
-        signalError(BAD_VALUE);
-        return;
-    }
-
-    CHECK(msg->findInt32("width", &mWidth));
-    CHECK(msg->findInt32("height", &mHeight));
-    if (!msg->findInt32("stride", &mStride)) {
-        mStride = mWidth;
-    }
-    if (!msg->findInt32("slice-height", &mSliceHeight)) {
-        mSliceHeight = mHeight;
-    }
-
-    mMaxInputSize = mWidth * mHeight * 4;   // room for ARGB8888
-    int32_t maxInputSize;
-    if (msg->findInt32("max-input-size", &maxInputSize)
-            && (size_t)maxInputSize > mMaxInputSize) {
-        mMaxInputSize = maxInputSize;
-    }
-
-    if (!msg->findInt32("color-format", &mColorFormatIn)) {
-        // default to OMX_COLOR_Format32bitARGB8888
-        mColorFormatIn = OMX_COLOR_Format32bitARGB8888;
-        msg->setInt32("color-format", mColorFormatIn);
-    }
-    mColorFormatOut = mColorFormatIn;
-
-    mMaxOutputSize = mWidth * mHeight * 4;  // room for ARGB8888
-
-    AString cacheDir;
-    if (!msg->findString("cacheDir", &cacheDir)) {
-        ALOGE("Failed to find cache directory in config message.");
-        signalError(NAME_NOT_FOUND);
-        return;
-    }
-
-    status_t err;
-    err = mFilter->configure(msg);
-    if (err != (status_t)OK) {
-        ALOGE("Failed to configure filter component, err %d", err);
-        signalError(err);
-        return;
-    }
-
-    mInputFormat = new AMessage();
-    mInputFormat->setString("mime", mime.c_str());
-    mInputFormat->setInt32("stride", mStride);
-    mInputFormat->setInt32("slice-height", mSliceHeight);
-    mInputFormat->setInt32("color-format", mColorFormatIn);
-    mInputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
-    mInputFormat->setInt32("width", mWidth);
-    mInputFormat->setInt32("height", mHeight);
-
-    mOutputFormat = new AMessage();
-    mOutputFormat->setString("mime", mime.c_str());
-    mOutputFormat->setInt32("stride", mStride);
-    mOutputFormat->setInt32("slice-height", mSliceHeight);
-    mOutputFormat->setInt32("color-format", mColorFormatOut);
-    mOutputFormat->setRect("crop", 0, 0, mStride, mSliceHeight);
-    mOutputFormat->setInt32("width", mWidth);
-    mOutputFormat->setInt32("height", mHeight);
-    mOutputFormat->setInt32("using-sw-renderer", 1);
-
-    mCallback->onComponentConfigured(mInputFormat, mOutputFormat);
-    mState = CONFIGURED;
-    ALOGV("Handled kWhatConfigureComponent.");
-}
-
-void MediaFilter::onStart() {
-    CHECK_EQ(mState, CONFIGURED);
-
-    allocateBuffersOnPort(kPortIndexInput);
-
-    allocateBuffersOnPort(kPortIndexOutput);
-
-    mCallback->onStartCompleted();
-
-    status_t err = mFilter->start();
-    if (err != (status_t)OK) {
-        ALOGE("Failed to start filter component, err %d", err);
-        signalError(err);
-        return;
-    }
-
-    mPortEOS[kPortIndexInput] = false;
-    mPortEOS[kPortIndexOutput] = false;
-    mInputEOSResult = OK;
-    mState = STARTED;
-
-    requestFillEmptyInput();
-    ALOGV("Handled kWhatStart.");
-}
-
-void MediaFilter::onInputBufferFilled(const sp<AMessage> &msg) {
-    sp<RefBase> obj;
-    CHECK(msg->findObject("buffer", &obj));
-    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
-    ssize_t index = -1;
-    BufferInfo *info = findBuffer(kPortIndexInput, buffer, &index);
-
-    if (mState != STARTED) {
-        // we're not running, so we'll just keep that buffer...
-        info->mStatus = BufferInfo::OWNED_BY_US;
-        return;
-    }
-
-    if (info->mGeneration != mGeneration) {
-        ALOGV("Caught a stale input buffer [index %zd]", index);
-        // buffer is stale (taken before a flush/shutdown) - repost it
-        CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
-        postFillThisBuffer(info);
-        return;
-    }
-
-    CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
-    info->mStatus = BufferInfo::OWNED_BY_US;
-
-    int32_t err = OK;
-    bool eos = false;
-
-    int32_t isCSD;
-    if (buffer != NULL && buffer->meta()->findInt32("csd", &isCSD)
-            && isCSD != 0) {
-        // ignore codec-specific data buffers
-        ALOGW("MediaFilter received a codec-specific data buffer");
-        postFillThisBuffer(info);
-        return;
-    }
-
-    int32_t tmp;
-    if (buffer != NULL && buffer->meta()->findInt32("eos", &tmp) && tmp) {
-        eos = true;
-        err = ERROR_END_OF_STREAM;
-    }
-
-    mAvailableInputBuffers.push_back(info);
-    processBuffers();
-
-    if (eos) {
-        mPortEOS[kPortIndexInput] = true;
-        mInputEOSResult = err;
-    }
-
-    ALOGV("Handled kWhatInputBufferFilled. [index %zd]", index);
-}
-
-void MediaFilter::onOutputBufferDrained(const sp<AMessage> &msg) {
-    sp<RefBase> obj;
-    CHECK(msg->findObject("buffer", &obj));
-    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
-    ssize_t index = -1;
-    BufferInfo *info = findBuffer(kPortIndexOutput, buffer, &index);
-
-    if (mState != STARTED) {
-        // we're not running, so we'll just keep that buffer...
-        info->mStatus = BufferInfo::OWNED_BY_US;
-        return;
-    }
-
-    if (info->mGeneration != mGeneration) {
-        ALOGV("Caught a stale output buffer [index %zd]", index);
-        // buffer is stale (taken before a flush/shutdown) - keep it
-        CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_US);
-        return;
-    }
-
-    CHECK_EQ(info->mStatus, BufferInfo::OWNED_BY_UPSTREAM);
-    info->mStatus = BufferInfo::OWNED_BY_US;
-
-    mAvailableOutputBuffers.push_back(info);
-
-    processBuffers();
-
-    ALOGV("Handled kWhatOutputBufferDrained. [index %zd]", index);
-}
-
-void MediaFilter::onShutdown(const sp<AMessage> &msg) {
-    mGeneration++;
-
-    if (mState != UNINITIALIZED) {
-        mFilter->reset();
-    }
-
-    int32_t keepComponentAllocated;
-    CHECK(msg->findInt32("keepComponentAllocated", &keepComponentAllocated));
-    if (!keepComponentAllocated || mState == UNINITIALIZED) {
-        mState = UNINITIALIZED;
-    } else {
-        mState = INITIALIZED;
-    }
-
-    if (keepComponentAllocated) {
-        mCallback->onStopCompleted();
-    } else {
-        mCallback->onReleaseCompleted();
-    }
-}
-
-void MediaFilter::onFlush() {
-    mGeneration++;
-
-    mAvailableInputBuffers.clear();
-    for (size_t i = 0; i < mBuffers[kPortIndexInput].size(); ++i) {
-        BufferInfo *info = &mBuffers[kPortIndexInput].editItemAt(i);
-        info->mStatus = BufferInfo::OWNED_BY_US;
-    }
-    mAvailableOutputBuffers.clear();
-    for (size_t i = 0; i < mBuffers[kPortIndexOutput].size(); ++i) {
-        BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
-        info->mStatus = BufferInfo::OWNED_BY_US;
-        mAvailableOutputBuffers.push_back(info);
-    }
-
-    mPortEOS[kPortIndexInput] = false;
-    mPortEOS[kPortIndexOutput] = false;
-    mInputEOSResult = OK;
-
-    mCallback->onFlushCompleted();
-    ALOGV("Posted kWhatFlushCompleted");
-
-    // MediaCodec returns all input buffers after flush, so in
-    // onInputBufferFilled we call postFillThisBuffer on them
-}
-
-void MediaFilter::onSetParameters(const sp<AMessage> &msg) {
-    CHECK(mState != STARTED);
-
-    status_t err = mFilter->setParameters(msg);
-    if (err != (status_t)OK) {
-        ALOGE("setParameters returned err %d", err);
-    }
-}
-
-void MediaFilter::onCreateInputSurface() {
-    CHECK(mState == CONFIGURED);
-
-    mGraphicBufferListener = new GraphicBufferListener;
-
-    sp<AMessage> notify = new AMessage();
-    notify->setTarget(this);
-    status_t err = mGraphicBufferListener->init(
-            notify, mStride, mSliceHeight, kBufferCountActual);
-
-    if (err != OK) {
-        ALOGE("Failed to init mGraphicBufferListener: %d", err);
-        signalError(err);
-        return;
-    }
-
-    mCallback->onInputSurfaceCreated(
-            nullptr, nullptr,
-            new BufferProducerWrapper(
-                    mGraphicBufferListener->getIGraphicBufferProducer()));
-}
-
-void MediaFilter::onInputFrameAvailable() {
-    BufferItem item = mGraphicBufferListener->getBufferItem();
-    sp<GraphicBuffer> buf = mGraphicBufferListener->getBuffer(item);
-
-    // get pointer to graphic buffer
-    void* bufPtr;
-    buf->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &bufPtr);
-
-    // HACK - there is no OMX_COLOR_FORMATTYPE value for RGBA, so the format
-    // conversion is hardcoded until we add this.
-    // TODO: check input format and convert only if necessary
-    // copy RGBA graphic buffer into temporary ARGB input buffer
-    BufferInfo *inputInfo = new BufferInfo;
-    inputInfo->mData = new MediaCodecBuffer(
-            mInputFormat, new ABuffer(buf->getWidth() * buf->getHeight() * 4));
-    ALOGV("Copying surface data into temp buffer.");
-    convertRGBAToARGB(
-            (uint8_t*)bufPtr, buf->getWidth(), buf->getHeight(),
-            buf->getStride(), inputInfo->mData->data());
-    inputInfo->mBufferID = item.mSlot;
-    inputInfo->mGeneration = mGeneration;
-    inputInfo->mOutputFlags = 0;
-    inputInfo->mStatus = BufferInfo::OWNED_BY_US;
-    inputInfo->mData->meta()->setInt64("timeUs", item.mTimestamp / 1000);
-
-    mAvailableInputBuffers.push_back(inputInfo);
-
-    mGraphicBufferListener->releaseBuffer(item);
-
-    signalProcessBuffers();
-}
-
-void MediaFilter::onSignalEndOfInputStream() {
-    // if using input surface, need to send an EOS output buffer
-    if (mGraphicBufferListener != NULL) {
-        Vector<BufferInfo> *outputBufs = &mBuffers[kPortIndexOutput];
-        BufferInfo* eosBuf;
-        bool foundBuf = false;
-        for (size_t i = 0; i < kBufferCountActual; i++) {
-            eosBuf = &outputBufs->editItemAt(i);
-            if (eosBuf->mStatus == BufferInfo::OWNED_BY_US) {
-                foundBuf = true;
-                break;
-            }
-        }
-
-        if (!foundBuf) {
-            ALOGE("onSignalEndOfInputStream failed to find an output buffer");
-            return;
-        }
-
-        eosBuf->mOutputFlags = BUFFER_FLAG_END_OF_STREAM;
-        eosBuf->mGeneration = mGeneration;
-        eosBuf->mData->setRange(0, 0);
-        postDrainThisBuffer(eosBuf);
-        ALOGV("Posted EOS on output buffer %u", eosBuf->mBufferID);
-    }
-
-    mPortEOS[kPortIndexOutput] = true;
-    mCallback->onSignaledInputEOS(OK);
-
-    ALOGV("Output stream saw EOS.");
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/RSFilter.cpp b/media/libstagefright/filters/RSFilter.cpp
deleted file mode 100644
index 225a375..0000000
--- a/media/libstagefright/filters/RSFilter.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "RSFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "RSFilter.h"
-
-namespace android {
-
-RSFilter::RSFilter() {
-
-}
-
-RSFilter::~RSFilter() {
-
-}
-
-status_t RSFilter::configure(const sp<AMessage> &msg) {
-    status_t err = SimpleFilter::configure(msg);
-    if (err != OK) {
-        return err;
-    }
-
-    if (!msg->findString("cacheDir", &mCacheDir)) {
-        ALOGE("Failed to find cache directory in config message.");
-        return NAME_NOT_FOUND;
-    }
-
-    sp<RenderScriptWrapper> wrapper;
-    if (!msg->findObject("rs-wrapper", (sp<RefBase>*)&wrapper)) {
-        ALOGE("Failed to find RenderScriptWrapper in config message.");
-        return NAME_NOT_FOUND;
-    }
-
-    mRS = wrapper->mContext;
-    mCallback = wrapper->mCallback;
-
-    return OK;
-}
-
-status_t RSFilter::start() {
-    // 32-bit elements for ARGB8888
-    RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
-    RSC::Type::Builder tb(mRS, e);
-    tb.setX(mWidth);
-    tb.setY(mHeight);
-    RSC::sp<const RSC::Type> t = tb.create();
-
-    mAllocIn = RSC::Allocation::createTyped(mRS, t);
-    mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
-    return OK;
-}
-
-void RSFilter::reset() {
-    mCallback.clear();
-    mAllocOut.clear();
-    mAllocIn.clear();
-    mRS.clear();
-}
-
-status_t RSFilter::setParameters(const sp<AMessage> &msg) {
-    return mCallback->handleSetParameters(msg);
-}
-
-status_t RSFilter::processBuffers(
-        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
-    mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
-    mCallback->processBuffers(mAllocIn.get(), mAllocOut.get());
-    mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/SaturationFilter.cpp b/media/libstagefright/filters/SaturationFilter.cpp
deleted file mode 100644
index 0a1df05..0000000
--- a/media/libstagefright/filters/SaturationFilter.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "SaturationFilter"
-
-#include <utils/Log.h>
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "SaturationFilter.h"
-
-namespace android {
-
-status_t SaturationFilter::configure(const sp<AMessage> &msg) {
-    status_t err = SimpleFilter::configure(msg);
-    if (err != OK) {
-        return err;
-    }
-
-    if (!msg->findString("cacheDir", &mCacheDir)) {
-        ALOGE("Failed to find cache directory in config message.");
-        return NAME_NOT_FOUND;
-    }
-
-    return OK;
-}
-
-status_t SaturationFilter::start() {
-    // TODO: use a single RS context object for entire application
-    mRS = new RSC::RS();
-
-    if (!mRS->init(mCacheDir.c_str())) {
-        ALOGE("Failed to initialize RenderScript context.");
-        return NO_INIT;
-    }
-
-    // 32-bit elements for ARGB8888
-    RSC::sp<const RSC::Element> e = RSC::Element::U8_4(mRS);
-
-    RSC::Type::Builder tb(mRS, e);
-    tb.setX(mWidth);
-    tb.setY(mHeight);
-    RSC::sp<const RSC::Type> t = tb.create();
-
-    mAllocIn = RSC::Allocation::createTyped(mRS, t);
-    mAllocOut = RSC::Allocation::createTyped(mRS, t);
-
-    mScript = new ScriptC_saturationARGB(mRS);
-
-    mScript->set_gSaturation(mSaturation);
-
-    return OK;
-}
-
-void SaturationFilter::reset() {
-    mScript.clear();
-    mAllocOut.clear();
-    mAllocIn.clear();
-    mRS.clear();
-}
-
-status_t SaturationFilter::setParameters(const sp<AMessage> &msg) {
-    sp<AMessage> params;
-    CHECK(msg->findMessage("params", &params));
-
-    float saturation;
-    if (params->findFloat("saturation", &saturation)) {
-        mSaturation = saturation;
-    }
-
-    return OK;
-}
-
-status_t SaturationFilter::processBuffers(
-        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
-    mAllocIn->copy1DRangeFrom(0, mWidth * mHeight, srcBuffer->data());
-    mScript->forEach_root(mAllocIn, mAllocOut);
-    mAllocOut->copy1DRangeTo(0, mWidth * mHeight, outBuffer->data());
-
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/SimpleFilter.cpp b/media/libstagefright/filters/SimpleFilter.cpp
deleted file mode 100644
index 6c1ca2c..0000000
--- a/media/libstagefright/filters/SimpleFilter.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-status_t SimpleFilter::configure(const sp<AMessage> &msg) {
-    CHECK(msg->findInt32("width", &mWidth));
-    CHECK(msg->findInt32("height", &mHeight));
-    if (!msg->findInt32("stride", &mStride)) {
-        mStride = mWidth;
-    }
-    if (!msg->findInt32("slice-height", &mSliceHeight)) {
-        mSliceHeight = mHeight;
-    }
-    CHECK(msg->findInt32("color-format", &mColorFormatIn));
-    mColorFormatOut = mColorFormatIn;
-
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/ZeroFilter.cpp b/media/libstagefright/filters/ZeroFilter.cpp
deleted file mode 100644
index 74b94b7..0000000
--- a/media/libstagefright/filters/ZeroFilter.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ZeroFilter"
-
-#include <media/MediaCodecBuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-
-#include "ZeroFilter.h"
-
-namespace android {
-
-status_t ZeroFilter::setParameters(const sp<AMessage> &msg) {
-    sp<AMessage> params;
-    CHECK(msg->findMessage("params", &params));
-
-    int32_t invert;
-    if (params->findInt32("invert", &invert)) {
-        mInvertData = (invert != 0);
-    }
-
-    return OK;
-}
-
-status_t ZeroFilter::processBuffers(
-        const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) {
-    // assuming identical input & output buffers, since we're a copy filter
-    if (mInvertData) {
-        uint32_t* src = (uint32_t*)srcBuffer->data();
-        uint32_t* dest = (uint32_t*)outBuffer->data();
-        for (size_t i = 0; i < srcBuffer->size() / 4; ++i) {
-            *(dest++) = *(src++) ^ 0xFFFFFFFF;
-        }
-    } else {
-        memcpy(outBuffer->data(), srcBuffer->data(), srcBuffer->size());
-    }
-    outBuffer->setRange(0, srcBuffer->size());
-
-    return OK;
-}
-
-}   // namespace android
diff --git a/media/libstagefright/filters/include/filters/ColorConvert.h b/media/libstagefright/filters/include/filters/ColorConvert.h
deleted file mode 100644
index 13faa02..0000000
--- a/media/libstagefright/filters/include/filters/ColorConvert.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COLOR_CONVERT_H_
-#define COLOR_CONVERT_H_
-
-#include <inttypes.h>
-
-namespace android {
-
-void YUVToRGB(
-        int32_t y, int32_t u, int32_t v,
-        int32_t* r, int32_t* g, int32_t* b);
-
-void convertYUV420spToARGB(
-        uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
-        uint8_t *dest);
-
-void convertYUV420spToRGB888(
-        uint8_t *pY, uint8_t *pUV, int32_t width, int32_t height,
-        uint8_t *dest);
-
-// TODO: remove when RGBA support is added to SoftwareRenderer
-void convertRGBAToARGB(
-        uint8_t *src, int32_t width, int32_t height, uint32_t stride,
-        uint8_t *dest);
-
-}   // namespace android
-
-#endif  // COLOR_CONVERT_H_
diff --git a/media/libstagefright/filters/include/filters/GraphicBufferListener.h b/media/libstagefright/filters/include/filters/GraphicBufferListener.h
deleted file mode 100644
index 586bf65..0000000
--- a/media/libstagefright/filters/include/filters/GraphicBufferListener.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRAPHIC_BUFFER_LISTENER_H_
-#define GRAPHIC_BUFFER_LISTENER_H_
-
-#include <gui/BufferQueue.h>
-
-namespace android {
-
-struct AMessage;
-
-struct GraphicBufferListener : public BufferQueue::ConsumerListener {
-public:
-    GraphicBufferListener() {};
-
-    status_t init(
-            const sp<AMessage> &notify,
-            size_t bufferWidth, size_t bufferHeight, size_t bufferCount);
-
-    virtual void onFrameAvailable(const BufferItem& item);
-    virtual void onBuffersReleased();
-    virtual void onSidebandStreamChanged();
-
-    // Returns the handle to the producer side of the BufferQueue.  Buffers
-    // queued on this will be received by GraphicBufferListener.
-    sp<IGraphicBufferProducer> getIGraphicBufferProducer() const {
-        return mProducer;
-    }
-
-    BufferItem getBufferItem();
-    sp<GraphicBuffer> getBuffer(BufferItem item);
-    status_t releaseBuffer(BufferItem item);
-
-    enum {
-        kWhatFrameAvailable = 'frav',
-    };
-
-private:
-    sp<AMessage> mNotify;
-    size_t mNumFramesAvailable;
-
-    mutable Mutex mMutex;
-
-    // Our BufferQueue interfaces. mProducer is passed to the producer through
-    // getIGraphicBufferProducer, and mConsumer is used internally to retrieve
-    // the buffers queued by the producer.
-    sp<IGraphicBufferProducer> mProducer;
-    sp<IGraphicBufferConsumer> mConsumer;
-
-    // Cache of GraphicBuffers from the buffer queue.
-    sp<GraphicBuffer> mBufferSlot[BufferQueue::NUM_BUFFER_SLOTS];
-};
-
-}   // namespace android
-
-#endif  // GRAPHIC_BUFFER_LISTENER_H
diff --git a/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h b/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
deleted file mode 100644
index a2aabfa..0000000
--- a/media/libstagefright/filters/include/filters/IntrinsicBlurFilter.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef INTRINSIC_BLUR_FILTER_H_
-#define INTRINSIC_BLUR_FILTER_H_
-
-#include "RenderScript.h"
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct IntrinsicBlurFilter : public SimpleFilter {
-public:
-    IntrinsicBlurFilter() : mBlurRadius(1.f) {};
-
-    virtual status_t configure(const sp<AMessage> &msg);
-    virtual status_t start();
-    virtual void reset();
-    virtual status_t setParameters(const sp<AMessage> &msg);
-    virtual status_t processBuffers(
-            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
-    virtual ~IntrinsicBlurFilter() {};
-
-private:
-    AString mCacheDir;
-    RSC::sp<RSC::RS> mRS;
-    RSC::sp<RSC::Allocation> mAllocIn;
-    RSC::sp<RSC::Allocation> mAllocOut;
-    RSC::sp<RSC::ScriptIntrinsicBlur> mBlur;
-    float mBlurRadius;
-};
-
-}   // namespace android
-
-#endif  // INTRINSIC_BLUR_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/RSFilter.h b/media/libstagefright/filters/include/filters/RSFilter.h
deleted file mode 100644
index 3326284..0000000
--- a/media/libstagefright/filters/include/filters/RSFilter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RS_FILTER_H_
-#define RS_FILTER_H_
-
-#include <media/stagefright/RenderScriptWrapper.h>
-#include <RenderScript.h>
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct AString;
-
-struct RSFilter : public SimpleFilter {
-public:
-    RSFilter();
-
-    virtual status_t configure(const sp<AMessage> &msg);
-    virtual status_t start();
-    virtual void reset();
-    virtual status_t setParameters(const sp<AMessage> &msg);
-    virtual status_t processBuffers(
-            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
-    virtual ~RSFilter();
-
-private:
-    AString mCacheDir;
-    sp<RenderScriptWrapper::RSFilterCallback> mCallback;
-    RSC::sp<RSC::RS> mRS;
-    RSC::sp<RSC::Allocation> mAllocIn;
-    RSC::sp<RSC::Allocation> mAllocOut;
-};
-
-}   // namespace android
-
-#endif  // RS_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/SaturationFilter.h b/media/libstagefright/filters/include/filters/SaturationFilter.h
deleted file mode 100644
index 317e469..0000000
--- a/media/libstagefright/filters/include/filters/SaturationFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SATURATION_FILTER_H_
-#define SATURATION_FILTER_H_
-
-#include <RenderScript.h>
-
-#include "ScriptC_saturationARGB.h"
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct SaturationFilter : public SimpleFilter {
-public:
-    SaturationFilter() : mSaturation(1.f) {};
-
-    virtual status_t configure(const sp<AMessage> &msg);
-    virtual status_t start();
-    virtual void reset();
-    virtual status_t setParameters(const sp<AMessage> &msg);
-    virtual status_t processBuffers(
-            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
-    virtual ~SaturationFilter() {};
-
-private:
-    AString mCacheDir;
-    RSC::sp<RSC::RS> mRS;
-    RSC::sp<RSC::Allocation> mAllocIn;
-    RSC::sp<RSC::Allocation> mAllocOut;
-    RSC::sp<ScriptC_saturationARGB> mScript;
-    float mSaturation;
-};
-
-}   // namespace android
-
-#endif  // SATURATION_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/SimpleFilter.h b/media/libstagefright/filters/include/filters/SimpleFilter.h
deleted file mode 100644
index a3c2d76..0000000
--- a/media/libstagefright/filters/include/filters/SimpleFilter.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SIMPLE_FILTER_H_
-#define SIMPLE_FILTER_H_
-
-#include <stdint.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-struct AMessage;
-class MediaCodecBuffer;
-
-struct SimpleFilter : public RefBase {
-public:
-    SimpleFilter() : mWidth(0), mHeight(0), mStride(0), mSliceHeight(0),
-            mColorFormatIn(0), mColorFormatOut(0) {};
-
-    virtual status_t configure(const sp<AMessage> &msg);
-
-    virtual status_t start() = 0;
-    virtual void reset() = 0;
-    virtual status_t setParameters(const sp<AMessage> &msg) = 0;
-    virtual status_t processBuffers(
-            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer) = 0;
-
-protected:
-    int32_t mWidth, mHeight;
-    int32_t mStride, mSliceHeight;
-    int32_t mColorFormatIn, mColorFormatOut;
-
-    virtual ~SimpleFilter() {};
-};
-
-}   // namespace android
-
-#endif  // SIMPLE_FILTER_H_
diff --git a/media/libstagefright/filters/include/filters/ZeroFilter.h b/media/libstagefright/filters/include/filters/ZeroFilter.h
deleted file mode 100644
index f941cc8..0000000
--- a/media/libstagefright/filters/include/filters/ZeroFilter.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ZERO_FILTER_H_
-#define ZERO_FILTER_H_
-
-#include "SimpleFilter.h"
-
-namespace android {
-
-struct ZeroFilter : public SimpleFilter {
-public:
-    ZeroFilter() : mInvertData(false) {};
-
-    virtual status_t start() { return OK; };
-    virtual void reset() {};
-    virtual status_t setParameters(const sp<AMessage> &msg);
-    virtual status_t processBuffers(
-            const sp<MediaCodecBuffer> &srcBuffer, const sp<MediaCodecBuffer> &outBuffer);
-
-protected:
-    virtual ~ZeroFilter() {};
-
-private:
-    bool mInvertData;
-};
-
-}   // namespace android
-
-#endif  // ZERO_FILTER_H_
diff --git a/media/libstagefright/filters/saturation.rscript b/media/libstagefright/filters/saturation.rscript
deleted file mode 100644
index 2c867ac..0000000
--- a/media/libstagefright/filters/saturation.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-// Sample script for RGB888 support (compare to saturationARGB.rs)
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar3 *v_in, uchar3 *v_out) {
-    // scale 0-255 uchar to 0-1.0 float
-    float3 in = {v_in->r * 0.003921569f, v_in->g * 0.003921569f,
-            v_in->b * 0.003921569f};
-
-    // apply saturation filter
-    float3 result = dot(in, gMonoMult);
-    result = mix(result, in, gSaturation);
-
-    // convert to uchar, copied from rsPackColorTo8888
-    v_out->x = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
-    v_out->y = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
-    v_out->z = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/media/libstagefright/filters/saturationARGB.rscript b/media/libstagefright/filters/saturationARGB.rscript
deleted file mode 100644
index 1de9dd8..0000000
--- a/media/libstagefright/filters/saturationARGB.rscript
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma version(1)
-#pragma rs java_package_name(com.android.rs.cppbasic)
-#pragma rs_fp_relaxed
-
-const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
-
-// global variables (parameters accessible to application code)
-float gSaturation = 1.0f;
-
-void root(const uchar4 *v_in, uchar4 *v_out) {
-    v_out->x = v_in->x; // don't modify A
-
-    // get RGB, scale 0-255 uchar to 0-1.0 float
-    float3 rgb = {v_in->y * 0.003921569f, v_in->z * 0.003921569f,
-            v_in->w * 0.003921569f};
-
-    // apply saturation filter
-    float3 result = dot(rgb, gMonoMult);
-    result = mix(result, rgb, gSaturation);
-
-    v_out->y = (uchar)clamp((result.r * 255.f + 0.5f), 0.f, 255.f);
-    v_out->z = (uchar)clamp((result.g * 255.f + 0.5f), 0.f, 255.f);
-    v_out->w = (uchar)clamp((result.b * 255.f + 0.5f), 0.f, 255.f);
-}
diff --git a/media/libstagefright/foundation/tests/AMessage_test.cpp b/media/libstagefright/foundation/tests/AMessage_test.cpp
deleted file mode 100644
index 2b11326..0000000
--- a/media/libstagefright/foundation/tests/AMessage_test.cpp
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "AData_test"
-
-#include <gtest/gtest.h>
-#include <utils/RefBase.h>
-
-#include <media/stagefright/foundation/AMessage.h>
-
-using namespace android;
-
-class AMessageTest : public ::testing::Test {
-};
-
-
-TEST(AMessage_tests, item_manipulation) {
-  sp<AMessage> m1 = new AMessage();
-
-  m1->setInt32("value", 2);
-  m1->setInt32("bar", 3);
-
-  int32_t i32;
-  EXPECT_TRUE(m1->findInt32("value", &i32));
-  EXPECT_EQ(2, i32);
-
-  EXPECT_TRUE(m1->findInt32("bar", &i32));
-  EXPECT_EQ(3, i32);
-
-
-  m1->setInt64("big", INT64_MAX);
-  m1->setInt64("smaller", INT64_MAX - 2);
-  m1->setInt64("smallest", 257);
-
-  int64_t i64;
-  EXPECT_TRUE(m1->findInt64("big", &i64));
-  EXPECT_EQ(INT64_MAX, i64);
-
-  EXPECT_TRUE(m1->findInt64("smaller", &i64));
-  EXPECT_EQ(INT64_MAX - 2, i64);
-
-  m1->setSize("size1", 257);
-  m1->setSize("size2", 1023);
-
-  size_t sizing;
-  EXPECT_TRUE(m1->findSize("size2", &sizing));
-  EXPECT_EQ(1023, sizing);
-  EXPECT_TRUE(m1->findSize("size1", &sizing));
-  EXPECT_EQ(257, sizing);
-
-  m1->setDouble("precise", 10.5);
-  m1->setDouble("small", 0.125);
-
-  double d;
-  EXPECT_TRUE(m1->findDouble("precise", &d));
-  EXPECT_EQ(10.5, d);
-
-  EXPECT_TRUE(m1->findDouble("small", &d));
-  EXPECT_EQ(0.125, d);
-
-  // should be unchanged from the top of the test
-  EXPECT_TRUE(m1->findInt32("bar", &i32));
-  EXPECT_EQ(3, i32);
-
-  EXPECT_FALSE(m1->findInt32("nonesuch", &i32));
-  EXPECT_FALSE(m1->findInt64("nonesuch2", &i64));
-  // types disagree, not found
-  EXPECT_FALSE(m1->findInt32("big", &i32));
-  EXPECT_FALSE(m1->findInt32("precise", &i32));
-
-  // integral types should come back true
-  EXPECT_TRUE(m1->findAsInt64("big", &i64));
-  EXPECT_EQ(INT64_MAX, i64);
-  EXPECT_TRUE(m1->findAsInt64("bar", &i64));
-  EXPECT_EQ(3, i64);
-  EXPECT_FALSE(m1->findAsInt64("precise", &i64));
-
-  // recovers ints, size, and floating point values
-  float value;
-  EXPECT_TRUE(m1->findAsFloat("value", &value));
-  EXPECT_EQ(2, value);
-  EXPECT_TRUE(m1->findAsFloat("smallest", &value));
-  EXPECT_EQ(257, value);
-  EXPECT_TRUE(m1->findAsFloat("size2", &value));
-  EXPECT_EQ(1023, value);
-  EXPECT_TRUE(m1->findAsFloat("precise", &value));
-  EXPECT_EQ(10.5, value);
-  EXPECT_TRUE(m1->findAsFloat("small", &value));
-  EXPECT_EQ(0.125, value);
-
-
-  // need to handle still:
-  // strings
-  // Object
-  // Buffer
-  // Message (nested)
-  //
-
-  // removal
-  m1->setInt32("shortlived", 2);
-  m1->setInt32("alittlelonger", 2);
-  EXPECT_EQ(OK, m1->removeEntryByName("shortlived"));
-  EXPECT_EQ(BAD_VALUE, m1->removeEntryByName(nullptr));
-  EXPECT_EQ(BAD_INDEX, m1->removeEntryByName("themythicalnonesuch"));
-  EXPECT_FALSE(m1->findInt32("shortlived", &i32));
-  EXPECT_TRUE(m1->findInt32("alittlelonger", &i32));
-
-  EXPECT_NE(OK, m1->removeEntryByName("notpresent"));
-
-}
-
diff --git a/media/libstagefright/include/ACodecBufferChannel.h b/media/libstagefright/include/ACodecBufferChannel.h
index da962d1..f3b0600 100644
--- a/media/libstagefright/include/ACodecBufferChannel.h
+++ b/media/libstagefright/include/ACodecBufferChannel.h
@@ -97,6 +97,7 @@
             const sp<MediaCodecBuffer> &buffer) override;
     virtual status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
+    virtual void pollForRenderedBuffers() override;
     virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
     virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
     virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
diff --git a/media/libstagefright/include/media/stagefright/ACodec.h b/media/libstagefright/include/media/stagefright/ACodec.h
index 5a21755..38a4c1e 100644
--- a/media/libstagefright/include/media/stagefright/ACodec.h
+++ b/media/libstagefright/include/media/stagefright/ACodec.h
@@ -18,6 +18,8 @@
 #define A_CODEC_H_
 
 #include <stdint.h>
+#include <list>
+#include <vector>
 #include <android/native_window.h>
 #include <media/hardware/MetadataBufferType.h>
 #include <media/MediaCodecInfo.h>
@@ -265,11 +267,11 @@
     sp<AMessage> mBaseOutputFormat;
 
     FrameRenderTracker mRenderTracker; // render information for buffers rendered by ACodec
-    Vector<BufferInfo> mBuffers[2];
+    std::vector<BufferInfo> mBuffers[2];
     bool mPortEOS[2];
     status_t mInputEOSResult;
 
-    List<sp<AMessage> > mDeferredQueue;
+    std::list<sp<AMessage>> mDeferredQueue;
 
     sp<AMessage> mLastOutputFormat;
     bool mIsVideo;
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index 5e84977..65d5246 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -21,7 +21,6 @@
 #include <media/AudioRecord.h>
 #include <media/AudioSystem.h>
 #include <media/stagefright/MediaSource.h>
-#include <media/MicrophoneInfo.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <utils/List.h>
 
@@ -83,7 +82,7 @@
     status_t addAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
     status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
 
-    status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+    status_t getActiveMicrophones(std::vector<media::MicrophoneInfoFw>* activeMicrophones);
     status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
     status_t setPreferredMicrophoneFieldDimension(float zoom);
 
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 48721ec..aa02151 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -407,6 +407,14 @@
      */
     virtual status_t renderOutputBuffer(
             const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) = 0;
+
+    /**
+     * Poll for updates about rendered buffers.
+     *
+     * Triggers callbacks to CodecCallback::onOutputFramesRendered.
+     */
+    virtual void pollForRenderedBuffers() = 0;
+
     /**
      * Discard a buffer to the underlying CodecBase object.
      *
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 6644e8e..29b196f 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -18,6 +18,7 @@
 
 #define MEDIA_CODEC_H_
 
+#include <list>
 #include <memory>
 #include <vector>
 
@@ -494,7 +495,7 @@
     // stop/flush/reset/release.
     Mutex mBufferLock;
 
-    List<size_t> mAvailPortBuffers[2];
+    std::list<size_t> mAvailPortBuffers[2];
     std::vector<BufferInfo> mPortBuffers[2];
 
     int32_t mDequeueInputTimeoutGeneration;
@@ -512,7 +513,7 @@
 
     sp<IDescrambler> mDescrambler;
 
-    List<sp<ABuffer> > mCSD;
+    std::list<sp<ABuffer> > mCSD;
 
     sp<AMessage> mActivityNotify;
 
@@ -628,6 +629,9 @@
                                                  // when low latency is on
     int64_t mInputBufferCounter;  // number of input buffers queued since last reset/flush
 
+    // A rescheduleable message that periodically polls for rendered buffers
+    sp<AMessage> mMsgPollForRenderedBuffers;
+
     class ReleaseSurface;
     std::unique_ptr<ReleaseSurface> mReleaseSurface;
 
diff --git a/media/libstagefright/include/media/stagefright/MediaFilter.h b/media/libstagefright/include/media/stagefright/MediaFilter.h
deleted file mode 100644
index 1255e0f..0000000
--- a/media/libstagefright/include/media/stagefright/MediaFilter.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MEDIA_FILTER_H_
-#define MEDIA_FILTER_H_
-
-#include <media/stagefright/CodecBase.h>
-
-namespace android {
-
-struct GraphicBufferListener;
-struct SimpleFilter;
-
-struct MediaFilter : public CodecBase {
-    MediaFilter();
-
-    virtual std::shared_ptr<BufferChannelBase> getBufferChannel() override;
-    virtual void initiateAllocateComponent(const sp<AMessage> &msg);
-    virtual void initiateConfigureComponent(const sp<AMessage> &msg);
-    virtual void initiateCreateInputSurface();
-    virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
-
-    virtual void initiateStart();
-    virtual void initiateShutdown(bool keepComponentAllocated = false);
-
-    virtual void signalFlush();
-    virtual void signalResume();
-
-    virtual void signalRequestIDRFrame();
-    virtual void signalSetParameters(const sp<AMessage> &msg);
-    virtual void signalEndOfInputStream();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-protected:
-    virtual ~MediaFilter();
-
-private:
-    struct BufferInfo {
-        enum Status {
-            OWNED_BY_US,
-            OWNED_BY_UPSTREAM,
-        };
-
-        uint32_t mBufferID;
-        int32_t mGeneration;
-        int32_t mOutputFlags;
-        Status mStatus;
-
-        sp<MediaCodecBuffer> mData;
-    };
-
-    class BufferChannel;
-
-    enum State {
-      UNINITIALIZED,
-      INITIALIZED,
-      CONFIGURED,
-      STARTED,
-    };
-
-    enum {
-        kWhatInputBufferFilled       = 'inpF',
-        kWhatOutputBufferDrained     = 'outD',
-        kWhatShutdown                = 'shut',
-        kWhatFlush                   = 'flus',
-        kWhatResume                  = 'resm',
-        kWhatAllocateComponent       = 'allo',
-        kWhatConfigureComponent      = 'conf',
-        kWhatCreateInputSurface      = 'cisf',
-        kWhatSignalEndOfInputStream  = 'eois',
-        kWhatStart                   = 'star',
-        kWhatSetParameters           = 'setP',
-        kWhatProcessBuffers          = 'proc',
-    };
-
-    enum {
-        kPortIndexInput  = 0,
-        kPortIndexOutput = 1
-    };
-
-    // member variables
-    AString mComponentName;
-    State mState;
-    status_t mInputEOSResult;
-    int32_t mWidth, mHeight;
-    int32_t mStride, mSliceHeight;
-    int32_t mColorFormatIn, mColorFormatOut;
-    size_t mMaxInputSize, mMaxOutputSize;
-    int32_t mGeneration;
-    sp<AMessage> mInputFormat;
-    sp<AMessage> mOutputFormat;
-
-    Vector<BufferInfo> mBuffers[2];
-    Vector<BufferInfo*> mAvailableInputBuffers;
-    Vector<BufferInfo*> mAvailableOutputBuffers;
-    bool mPortEOS[2];
-
-    sp<SimpleFilter> mFilter;
-    sp<GraphicBufferListener> mGraphicBufferListener;
-
-    std::shared_ptr<BufferChannel> mBufferChannel;
-
-    // helper functions
-    void signalProcessBuffers();
-    void signalError(status_t error);
-
-    status_t allocateBuffersOnPort(OMX_U32 portIndex);
-    BufferInfo *findBuffer(
-            uint32_t portIndex, const sp<MediaCodecBuffer> &buffer,
-            ssize_t *index = NULL);
-    void postFillThisBuffer(BufferInfo *info);
-    void postDrainThisBuffer(BufferInfo *info);
-    void postEOS();
-    void requestFillEmptyInput();
-    void processBuffers();
-
-    void onAllocateComponent(const sp<AMessage> &msg);
-    void onConfigureComponent(const sp<AMessage> &msg);
-    void onStart();
-    void onInputBufferFilled(const sp<AMessage> &msg);
-    void onOutputBufferDrained(const sp<AMessage> &msg);
-    void onShutdown(const sp<AMessage> &msg);
-    void onFlush();
-    void onSetParameters(const sp<AMessage> &msg);
-    void onCreateInputSurface();
-    void onInputFrameAvailable();
-    void onSignalEndOfInputStream();
-
-    DISALLOW_EVIL_CONSTRUCTORS(MediaFilter);
-};
-
-}  // namespace android
-
-#endif  // MEDIA_FILTER_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaMuxer.h b/media/libstagefright/include/media/stagefright/MediaMuxer.h
index e97a65e..33aaf11 100644
--- a/media/libstagefright/include/media/stagefright/MediaMuxer.h
+++ b/media/libstagefright/include/media/stagefright/MediaMuxer.h
@@ -48,9 +48,13 @@
 // deleting the output file after stop.
 struct MediaMuxer : public MediaMuxerBase {
 public:
-    // Construct the muxer with the file descriptor. Note that the MediaMuxer
-    // will close this file at stop().
-    MediaMuxer(int fd, OutputFormat format);
+    /**
+     * Creates the muxer for a given output format.
+     * @param fd : file descriptor of the output file.
+     * @param format : output format of the muxer. e.g.: webm/mp4/ogg
+     * @return writer's object or nullptr if error.
+     */
+    static MediaMuxer* create(int fd, OutputFormat format);
 
     virtual ~MediaMuxer();
 
@@ -127,6 +131,11 @@
     sp<AMessage> getTrackFormat(size_t idx);
 
 private:
+    // Construct the muxer with the file descriptor. Note that the MediaMuxer
+    // will close this file at stop().
+    // This constructor is made private to ensure that MediaMuxer::create() is used instead.
+    MediaMuxer(int fd, OutputFormat format);
+
     const OutputFormat mFormat;
     sp<MediaWriter> mWriter;
     Vector< sp<MediaAdapter> > mTrackList;  // Each track has its MediaAdapter.
diff --git a/media/libstagefright/include/media/stagefright/MediaWriter.h b/media/libstagefright/include/media/stagefright/MediaWriter.h
index 9f20185..2b14811 100644
--- a/media/libstagefright/include/media/stagefright/MediaWriter.h
+++ b/media/libstagefright/include/media/stagefright/MediaWriter.h
@@ -31,6 +31,29 @@
           mMaxFileDurationLimitUs(0) {
     }
 
+    // Returns true if the file descriptor is opened using a mode
+    // which meets minimum writer/muxer requirements.
+    static bool isFdOpenModeValid(int fd) {
+        // check for invalid file descriptor.
+        int flags = fcntl(fd, F_GETFL);
+        if (flags == -1) {
+            ALOGE("Invalid File Status Flags and/or mode : %d", flags);
+            return false;
+        }
+        // fd must be in read-write mode or write-only mode.
+        if ((flags & (O_RDWR | O_WRONLY)) == 0) {
+            ALOGE("File must be writable");
+            return false;
+        }
+        // Verify fd is seekable
+        off64_t off = lseek64(fd, 0, SEEK_SET);
+        if (off < 0) {
+            ALOGE("File descriptor is not seekable");
+            return false;
+        }
+        return true;
+    }
+
     virtual status_t addSource(const sp<MediaSource> &source) = 0;
     virtual bool reachedEOS() = 0;
     virtual status_t start(MetaData *params = NULL) = 0;
diff --git a/media/libstagefright/include/media/stagefright/MetaDataBase.h b/media/libstagefright/include/media/stagefright/MetaDataBase.h
index 31faafb..a7d2eb9 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataBase.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataBase.h
@@ -117,6 +117,12 @@
     kKeyVideoProfile      = 'vprf',  // int32_t
     kKeyVideoLevel        = 'vlev',  // int32_t
 
+    // audio profile and level
+    // The codec framework doesn't distinguish between video and audio profiles,
+    // so there is no need to define a separate key
+    kKeyAudioProfile      = 'vprf',  // int32_t
+    kKeyAudioLevel        = 'vlev',  // int32_t
+
     kKey2ByteNalLength    = '2NAL',  // int32_t (bool)
 
     // Identify the file output format for authoring
@@ -278,6 +284,18 @@
     kKeyLastSampleIndexInChunk = 'lsic',  //int64_t, index of last sample in a chunk.
     kKeySampleTimeBeforeAppend = 'lsba', // int64_t, timestamp of last sample of a track.
 
+    // DVB component tag
+    kKeyDvbComponentTag = 'copt', // int32_t, component tag for DVB video/audio/subtitle
+
+    // DVB audio description
+    kKeyDvbAudioDescription = 'addt', // bool (int32_t), DVB audio description only defined for
+                                      // audio component
+
+    // DVB teletext magazine number
+    kKeyDvbTeletextMagazineNumber = 'ttxm', // int32_t, DVB teletext magazine number
+
+    // DVB teletext page number
+    kKeyDvbTeletextPageNumber = 'ttxp', // int32_t, DVB teletext page number
 };
 
 enum {
diff --git a/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h b/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h
deleted file mode 100644
index b42649e..0000000
--- a/media/libstagefright/include/media/stagefright/RenderScriptWrapper.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RENDERSCRIPT_WRAPPER_H_
-#define RENDERSCRIPT_WRAPPER_H_
-
-#include <RenderScript.h>
-
-namespace android {
-
-struct RenderScriptWrapper : public RefBase {
-public:
-    struct RSFilterCallback : public RefBase {
-    public:
-        // called by RSFilter to process each input buffer
-        virtual status_t processBuffers(
-                RSC::Allocation* inBuffer,
-                RSC::Allocation* outBuffer) = 0;
-
-        virtual status_t handleSetParameters(const sp<AMessage> &msg) = 0;
-    };
-
-    sp<RSFilterCallback> mCallback;
-    RSC::sp<RSC::RS> mContext;
-};
-
-}   // namespace android
-
-#endif  // RENDERSCRIPT_WRAPPER_H_
diff --git a/media/libstagefright/renderfright/Android.bp b/media/libstagefright/renderfright/Android.bp
index 3c00a1c..3598e8d 100644
--- a/media/libstagefright/renderfright/Android.bp
+++ b/media/libstagefright/renderfright/Android.bp
@@ -32,6 +32,7 @@
         "libEGL",
         "libGLESv1_CM",
         "libGLESv2",
+        "libvulkan",
         "liblog",
         "libnativewindow",
         "libprocessgroup",
diff --git a/media/libstagefright/renderfright/gl/ProgramCache.cpp b/media/libstagefright/renderfright/gl/ProgramCache.cpp
index 56d35a9..af55172 100644
--- a/media/libstagefright/renderfright/gl/ProgramCache.cpp
+++ b/media/libstagefright/renderfright/gl/ProgramCache.cpp
@@ -373,7 +373,11 @@
                                     return color * slope;
                                 } else if (nits < x1) {
                                     // scale [x0, x1] to [y0, y1] linearly
-                                    float slope = (y1 - y0) / (x1 - x0);
+                                    // Use highp since some compilers may do this
+                                    // operation as reciprocal multiplication with
+                                    // re-association that could exceed the range
+                                    // of mediump float.
+                                    highp float slope = (y1 - y0) / (x1 - x0);
                                     nits = y0 + (nits - x0) * slope;
                                 } else if (nits < x2) {
                                     // scale [x1, x2] to [y1, y2] using Hermite interp
diff --git a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
index c43e1f8..19c8577 100644
--- a/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
+++ b/media/libstagefright/tests/HEVC/HEVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <fstream>
+#include <memory>
 
 #include <media/stagefright/foundation/ABitReader.h>
 #include <HevcUtils.h>
@@ -88,10 +89,10 @@
         stringLine >> type >> chunkLength;
         ASSERT_GT(chunkLength, 0) << "Length of data chunk must be greater than 0";
 
-        char *data = (char *)malloc(chunkLength);
+        std::unique_ptr<char[]> data(new char[chunkLength]);
         ASSERT_NE(data, nullptr) << "Failed to allocate data buffer of size: " << chunkLength;
 
-        mMediaFileStream.read(data, chunkLength);
+        mMediaFileStream.read(data.get(), chunkLength);
         ASSERT_EQ(mMediaFileStream.gcount(), chunkLength)
                 << "Failed to read complete file, bytes read: " << mMediaFileStream.gcount();
 
@@ -105,7 +106,7 @@
         offset += 3;
         ASSERT_LE(offset, chunkLength) << "NAL unit offset must not exceed the chunk length";
 
-        uint8_t *nalUnit = (uint8_t *)(data + offset);
+        uint8_t *nalUnit = (uint8_t *)(data.get() + offset);
         size_t nalUnitLength = chunkLength - offset;
 
         // Add NAL units only if they're of type: VPS/SPS/PPS/SEI
@@ -118,20 +119,18 @@
             size_t sizeNalUnit = hevcParams.getSize(index);
             ASSERT_EQ(sizeNalUnit, nalUnitLength) << "Invalid size returned for NAL: " << type;
 
-            uint8_t *destination = (uint8_t *)malloc(nalUnitLength);
+            std::unique_ptr<uint8_t[]> destination(new uint8_t[nalUnitLength]);
             ASSERT_NE(destination, nullptr)
                     << "Failed to allocate buffer of size: " << nalUnitLength;
 
-            bool status = hevcParams.write(index, destination, nalUnitLength);
+            bool status = hevcParams.write(index, destination.get(), nalUnitLength);
             ASSERT_TRUE(status) << "Unable to write NAL Unit data";
 
-            free(destination);
             index++;
         } else {
             err = hevcParams.addNalUnit(nalUnit, nalUnitLength);
             ASSERT_NE(err, (status_t)OK) << "Invalid NAL Unit added, type: " << type;
         }
-        free(data);
     }
 
     size_t numNalUnits = hevcParams.getNumNalUnitsOfType(kVPSCode);
@@ -166,10 +165,10 @@
             << "Expected NAL type: 34(PPS), found: " << typeNalUnit;
 
     size_t hvccBoxSize = kHvccBoxMaxSize;
-    uint8_t *hvcc = (uint8_t *)malloc(kHvccBoxMaxSize);
+    std::unique_ptr<uint8_t[]> hvcc(new uint8_t[kHvccBoxMaxSize]);
     ASSERT_NE(hvcc, nullptr) << "Failed to allocate a hvcc buffer of size: " << kHvccBoxMaxSize;
 
-    err = hevcParams.makeHvcc(hvcc, &hvccBoxSize, kNALSizeLength);
+    err = hevcParams.makeHvcc(hvcc.get(), &hvccBoxSize, kNALSizeLength);
     ASSERT_EQ(err, (status_t)OK) << "Unable to create hvcc box";
 
     ASSERT_GT(hvccBoxSize, kHvccBoxMinSize)
@@ -179,8 +178,6 @@
     if (frameRate != mFrameRate)
         cout << "[   WARN   ] Expected frame rate: " << mFrameRate << " Found: " << frameRate
              << endl;
-
-    free(hvcc);
 }
 
 // Info File contains the type and length for each chunk/frame
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
index d94c8ff..9f46a74 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.cpp
@@ -66,8 +66,8 @@
     for (size_t i = 0; i < extractor->countTracks(); ++i) {
         sp<MetaData> meta = extractor->getTrackMetaData(i);
 
-        const char *trackMime;
-        if (!strcasecmp(mime.c_str(), trackMime)) {
+        std::string trackMime = dataProvider->PickValueInArray(kTestedMimeTypes);
+        if (!strcasecmp(mime.c_str(), trackMime.c_str())) {
             sp<IMediaSource> track = extractor->getTrack(i);
             if (track == NULL) {
                 return NULL;
diff --git a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
index 98bfb94..6856ac0 100644
--- a/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
+++ b/media/libstagefright/tests/fuzzers/FuzzerMediaUtility.h
@@ -42,6 +42,51 @@
     kMaxValue = MPEG2TS,
 };
 
+static std::string kTestedMimeTypes[] = {"audio/3gpp",
+                                         "audio/amr-wb",
+                                         "audio/vorbis",
+                                         "audio/opus",
+                                         "audio/mp4a-latm",
+                                         "audio/mpeg",
+                                         "audio/mpeg-L1",
+                                         "audio/mpeg-L2",
+                                         "audio/midi",
+                                         "audio/qcelp",
+                                         "audio/g711-alaw",
+                                         "audio/g711-mlaw",
+                                         "audio/flac",
+                                         "audio/aac-adts",
+                                         "audio/gsm",
+                                         "audio/ac3",
+                                         "audio/eac3",
+                                         "audio/eac3-joc",
+                                         "audio/ac4",
+                                         "audio/scrambled",
+                                         "audio/alac",
+                                         "audio/x-ms-wma",
+                                         "audio/x-adpcm-ms",
+                                         "audio/x-adpcm-dvi-ima",
+                                         "video/avc",
+                                         "video/hevc",
+                                         "video/mp4v-es",
+                                         "video/3gpp",
+                                         "video/x-vnd.on2.vp8",
+                                         "video/x-vnd.on2.vp9",
+                                         "video/av01",
+                                         "video/mpeg2",
+                                         "video/dolby-vision",
+                                         "video/scrambled",
+                                         "video/divx",
+                                         "video/divx3",
+                                         "video/xvid",
+                                         "video/x-motion-jpeg",
+                                         "text/3gpp-tt",
+                                         "application/x-subrip",
+                                         "text/vtt",
+                                         "text/cea-608",
+                                         "text/cea-708",
+                                         "application/x-id3v4"};
+
 std::string genMimeType(FuzzedDataProvider *dataProvider);
 sp<IMediaExtractor> genMediaExtractor(FuzzedDataProvider *dataProvider, uint16_t dataAmount);
 sp<MediaSource> genMediaSource(FuzzedDataProvider *dataProvider, uint16_t maxMediaBlobSize);
diff --git a/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp b/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
index 5df3267..70d73c8 100644
--- a/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
+++ b/media/libstagefright/tests/fuzzers/MediaMuxerFuzzer.cpp
@@ -52,7 +52,10 @@
 
   MediaMuxer::OutputFormat format =
       (MediaMuxer::OutputFormat)fdp.ConsumeIntegralInRange<int32_t>(0, 4);
-  sp<MediaMuxer> mMuxer(new MediaMuxer(fd, format));
+  sp<MediaMuxer> mMuxer = MediaMuxer::create(fd, format);
+  if (mMuxer == nullptr) {
+    return 0;
+  }
 
   while (fdp.remaining_bytes() > 1) {
     switch (fdp.ConsumeIntegralInRange<uint8_t>(0, 4)) {
diff --git a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
index a8e64b6..ecdaac5 100644
--- a/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
+++ b/media/libstagefright/tests/mediacodec/MediaCodecTest.cpp
@@ -70,6 +70,7 @@
     MOCK_METHOD(status_t, discardBuffer, (const sp<MediaCodecBuffer> &buffer), (override));
     MOCK_METHOD(void, getInputBufferArray, (Vector<sp<MediaCodecBuffer>> *array), (override));
     MOCK_METHOD(void, getOutputBufferArray, (Vector<sp<MediaCodecBuffer>> *array), (override));
+    MOCK_METHOD(void, pollForRenderedBuffers, (), (override));
 };
 
 class MockCodec : public CodecBase {
diff --git a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
index f934b54..b2044d3 100644
--- a/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
+++ b/media/libstagefright/timedtext/test/TimedTextUnitTest.cpp
@@ -22,6 +22,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <fstream>
+#include <memory>
 
 #include <binder/Parcel.h>
 #include <media/stagefright/foundation/AString.h>
@@ -240,10 +241,10 @@
 
                     if (remaining < tempFontNameLength) break;
                     const uint8_t *tmpFont = tmpData;
-                    char *tmpFontName = strndup((const char *)tmpFont, tempFontNameLength);
+                    std::unique_ptr<char[]> tmpFontName(new char[tempFontNameLength]);
+                    strncpy(tmpFontName.get(), (const char *)tmpFont, tempFontNameLength);
                     ASSERT_NE(tmpFontName, nullptr) << "Font Name is null";
-                    ALOGI("FontName = %s", tmpFontName);
-                    free(tmpFontName);
+                    ALOGI("FontName = %s", tmpFontName.get());
                     tmpData += tempFontNameLength;
                     remaining -= tempFontNameLength;
                     fontRecordEntries.push_back({tempFontID, tempFontNameLength, tmpFont});
diff --git a/media/libstagefright/webm/WebmFrameThread.cpp b/media/libstagefright/webm/WebmFrameThread.cpp
index 59ce8db..cdbd745 100644
--- a/media/libstagefright/webm/WebmFrameThread.cpp
+++ b/media/libstagefright/webm/WebmFrameThread.cpp
@@ -197,7 +197,6 @@
 }
 
 status_t WebmFrameSinkThread::stop() {
-    mDone = true;
     mVideoFrames.push(WebmFrame::EOS);
     mAudioFrames.push(WebmFrame::EOS);
     return WebmFrameThread::stop();
diff --git a/media/libstagefright/webm/WebmWriter.cpp b/media/libstagefright/webm/WebmWriter.cpp
index 5eaadbd..3823c36 100644
--- a/media/libstagefright/webm/WebmWriter.cpp
+++ b/media/libstagefright/webm/WebmWriter.cpp
@@ -54,6 +54,19 @@
 
 static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
 
+bool WebmWriter::isFdOpenModeValid(int fd) {
+    // check for invalid file descriptor.
+    if (!MediaWriter::isFdOpenModeValid(fd)) {
+        return false;
+    }
+    int flags = fcntl(fd, F_GETFL);
+    if ((flags & O_RDWR) == 0) {
+        ALOGE("File must be in read-write mode for webm writer");
+        return false;
+    }
+    return true;
+}
+
 WebmWriter::WebmWriter(int fd)
     : mFd(dup(fd)),
       mInitCheck(mFd < 0 ? NO_INIT : OK),
diff --git a/media/libstagefright/webm/include/webm/WebmWriter.h b/media/libstagefright/webm/include/webm/WebmWriter.h
index ed5bc4c..e339add 100644
--- a/media/libstagefright/webm/include/webm/WebmWriter.h
+++ b/media/libstagefright/webm/include/webm/WebmWriter.h
@@ -36,6 +36,10 @@
 
 class WebmWriter : public MediaWriter {
 public:
+    // Returns true if the file descriptor is opened using a mode
+    // which is compatible with WebmWriter.
+    // Note that this overloads that method in the base class.
+    static bool isFdOpenModeValid(int fd);
     explicit WebmWriter(int fd);
     ~WebmWriter() { reset(); }
 
diff --git a/media/mediaserver/Android.bp b/media/mediaserver/Android.bp
index edddaa4..19f9549 100644
--- a/media/mediaserver/Android.bp
+++ b/media/mediaserver/Android.bp
@@ -26,7 +26,33 @@
     ],
 }
 
-cc_binary {
+prebuilt_etc {
+    name: "mediaserver.zygote64_32.rc",
+    src: "mediaserver.zygote64_32.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "mediaserver.zygote64.rc",
+    src: "mediaserver.zygote64.rc",
+    sub_dir: "init/hw",
+}
+
+soong_config_module_type {
+    name: "mediaserver_cc_binary",
+    module_type: "cc_binary",
+    config_namespace: "ANDROID",
+    bool_variables: ["TARGET_DYNAMIC_64_32_MEDIASERVER"],
+    properties: [
+        "compile_multilib",
+        "init_rc",
+        "multilib.lib32.suffix",
+        "multilib.lib64.suffix",
+        "required",
+    ],
+}
+
+mediaserver_cc_binary {
     name: "mediaserver",
 
     srcs: ["main_mediaserver.cpp"],
@@ -55,12 +81,32 @@
     // ****************************************************************
     compile_multilib: "prefer32",
 
-    init_rc: ["mediaserver.rc"],
-
     cflags: [
         "-Werror",
         "-Wall",
     ],
 
     vintf_fragments: ["manifest_media_c2_software.xml"],
+
+    soong_config_variables: {
+        TARGET_DYNAMIC_64_32_MEDIASERVER: {
+            compile_multilib: "both",
+            multilib: {
+                lib32: {
+                    suffix: "32",
+                },
+                lib64: {
+                    suffix: "64",
+                },
+            },
+            required: [
+                "mediaserver.zygote64_32.rc",
+                "mediaserver.zygote64.rc",
+            ],
+            init_rc: ["mediaserver_dynamic.rc"],
+            conditions_default: {
+                init_rc: ["mediaserver.rc"],
+            },
+        },
+    },
 }
diff --git a/media/mediaserver/mediaserver.zygote64.rc b/media/mediaserver/mediaserver.zygote64.rc
new file mode 100644
index 0000000..8842b01
--- /dev/null
+++ b/media/mediaserver/mediaserver.zygote64.rc
@@ -0,0 +1,6 @@
+service media /system/bin/mediaserver64
+    class main
+    user media
+    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mediaserver/mediaserver.zygote64_32.rc b/media/mediaserver/mediaserver.zygote64_32.rc
new file mode 100644
index 0000000..4039073
--- /dev/null
+++ b/media/mediaserver/mediaserver.zygote64_32.rc
@@ -0,0 +1,6 @@
+service media /system/bin/mediaserver32
+    class main
+    user media
+    group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm
+    ioprio rt 4
+    task_profiles ProcessCapacityHigh HighPerformance
diff --git a/media/mediaserver/mediaserver_dynamic.rc b/media/mediaserver/mediaserver_dynamic.rc
new file mode 100644
index 0000000..65d5c40
--- /dev/null
+++ b/media/mediaserver/mediaserver_dynamic.rc
@@ -0,0 +1,4 @@
+on property:init.svc.media=*
+    setprop init.svc.mediadrm ${init.svc.media}
+
+import /system/etc/init/hw/mediaserver.${ro.zygote}.rc
diff --git a/media/libstagefright/bqhelper/Android.bp b/media/module/bqhelper/Android.bp
similarity index 97%
rename from media/libstagefright/bqhelper/Android.bp
rename to media/module/bqhelper/Android.bp
index 0e2b472..df658ee 100644
--- a/media/libstagefright/bqhelper/Android.bp
+++ b/media/module/bqhelper/Android.bp
@@ -4,7 +4,6 @@
     // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
 }
 
 cc_defaults {
diff --git a/media/libstagefright/bqhelper/FrameDropper.cpp b/media/module/bqhelper/FrameDropper.cpp
similarity index 100%
rename from media/libstagefright/bqhelper/FrameDropper.cpp
rename to media/module/bqhelper/FrameDropper.cpp
diff --git a/media/libstagefright/bqhelper/GraphicBufferSource.cpp b/media/module/bqhelper/GraphicBufferSource.cpp
similarity index 100%
rename from media/libstagefright/bqhelper/GraphicBufferSource.cpp
rename to media/module/bqhelper/GraphicBufferSource.cpp
diff --git a/media/libstagefright/bqhelper/TEST_MAPPING b/media/module/bqhelper/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/bqhelper/TEST_MAPPING
rename to media/module/bqhelper/TEST_MAPPING
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h b/media/module/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h
similarity index 100%
rename from media/libstagefright/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h
rename to media/module/bqhelper/include/media/stagefright/bqhelper/ComponentWrapper.h
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h b/media/module/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
similarity index 100%
rename from media/libstagefright/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
rename to media/module/bqhelper/include/media/stagefright/bqhelper/FrameDropper.h
diff --git a/media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h b/media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
similarity index 100%
rename from media/libstagefright/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
rename to media/module/bqhelper/include/media/stagefright/bqhelper/GraphicBufferSource.h
diff --git a/media/libstagefright/bqhelper/tests/Android.bp b/media/module/bqhelper/tests/Android.bp
similarity index 88%
rename from media/libstagefright/bqhelper/tests/Android.bp
rename to media/module/bqhelper/tests/Android.bp
index 95953ee..3004ec4 100644
--- a/media/libstagefright/bqhelper/tests/Android.bp
+++ b/media/module/bqhelper/tests/Android.bp
@@ -4,7 +4,6 @@
     // all of the 'license_kinds' from "frameworks_av_media_libstagefright_license"
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_av_media_libstagefright_license"],
 }
 
 cc_test {
diff --git a/media/libstagefright/bqhelper/tests/FrameDropper_test.cpp b/media/module/bqhelper/tests/FrameDropper_test.cpp
similarity index 100%
rename from media/libstagefright/bqhelper/tests/FrameDropper_test.cpp
rename to media/module/bqhelper/tests/FrameDropper_test.cpp
diff --git a/media/bufferpool/1.0/Accessor.cpp b/media/module/bufferpool/1.0/Accessor.cpp
similarity index 100%
rename from media/bufferpool/1.0/Accessor.cpp
rename to media/module/bufferpool/1.0/Accessor.cpp
diff --git a/media/bufferpool/1.0/Accessor.h b/media/module/bufferpool/1.0/Accessor.h
similarity index 100%
rename from media/bufferpool/1.0/Accessor.h
rename to media/module/bufferpool/1.0/Accessor.h
diff --git a/media/bufferpool/1.0/AccessorImpl.cpp b/media/module/bufferpool/1.0/AccessorImpl.cpp
similarity index 100%
rename from media/bufferpool/1.0/AccessorImpl.cpp
rename to media/module/bufferpool/1.0/AccessorImpl.cpp
diff --git a/media/bufferpool/1.0/AccessorImpl.h b/media/module/bufferpool/1.0/AccessorImpl.h
similarity index 100%
rename from media/bufferpool/1.0/AccessorImpl.h
rename to media/module/bufferpool/1.0/AccessorImpl.h
diff --git a/media/bufferpool/1.0/Android.bp b/media/module/bufferpool/1.0/Android.bp
similarity index 100%
rename from media/bufferpool/1.0/Android.bp
rename to media/module/bufferpool/1.0/Android.bp
diff --git a/media/bufferpool/1.0/BufferPoolClient.cpp b/media/module/bufferpool/1.0/BufferPoolClient.cpp
similarity index 100%
rename from media/bufferpool/1.0/BufferPoolClient.cpp
rename to media/module/bufferpool/1.0/BufferPoolClient.cpp
diff --git a/media/bufferpool/1.0/BufferPoolClient.h b/media/module/bufferpool/1.0/BufferPoolClient.h
similarity index 100%
rename from media/bufferpool/1.0/BufferPoolClient.h
rename to media/module/bufferpool/1.0/BufferPoolClient.h
diff --git a/media/bufferpool/1.0/BufferStatus.cpp b/media/module/bufferpool/1.0/BufferStatus.cpp
similarity index 100%
rename from media/bufferpool/1.0/BufferStatus.cpp
rename to media/module/bufferpool/1.0/BufferStatus.cpp
diff --git a/media/bufferpool/1.0/BufferStatus.h b/media/module/bufferpool/1.0/BufferStatus.h
similarity index 100%
rename from media/bufferpool/1.0/BufferStatus.h
rename to media/module/bufferpool/1.0/BufferStatus.h
diff --git a/media/bufferpool/1.0/ClientManager.cpp b/media/module/bufferpool/1.0/ClientManager.cpp
similarity index 100%
rename from media/bufferpool/1.0/ClientManager.cpp
rename to media/module/bufferpool/1.0/ClientManager.cpp
diff --git a/media/bufferpool/1.0/Connection.cpp b/media/module/bufferpool/1.0/Connection.cpp
similarity index 100%
rename from media/bufferpool/1.0/Connection.cpp
rename to media/module/bufferpool/1.0/Connection.cpp
diff --git a/media/bufferpool/1.0/Connection.h b/media/module/bufferpool/1.0/Connection.h
similarity index 100%
rename from media/bufferpool/1.0/Connection.h
rename to media/module/bufferpool/1.0/Connection.h
diff --git a/media/bufferpool/1.0/TEST_MAPPING b/media/module/bufferpool/1.0/TEST_MAPPING
similarity index 100%
rename from media/bufferpool/1.0/TEST_MAPPING
rename to media/module/bufferpool/1.0/TEST_MAPPING
diff --git a/media/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h b/media/module/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h
similarity index 100%
rename from media/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h
rename to media/module/bufferpool/1.0/include/bufferpool/BufferPoolTypes.h
diff --git a/media/bufferpool/1.0/include/bufferpool/ClientManager.h b/media/module/bufferpool/1.0/include/bufferpool/ClientManager.h
similarity index 100%
rename from media/bufferpool/1.0/include/bufferpool/ClientManager.h
rename to media/module/bufferpool/1.0/include/bufferpool/ClientManager.h
diff --git a/media/bufferpool/1.0/vts/Android.bp b/media/module/bufferpool/1.0/vts/Android.bp
similarity index 100%
rename from media/bufferpool/1.0/vts/Android.bp
rename to media/module/bufferpool/1.0/vts/Android.bp
diff --git a/media/bufferpool/1.0/vts/OWNERS b/media/module/bufferpool/1.0/vts/OWNERS
similarity index 100%
rename from media/bufferpool/1.0/vts/OWNERS
rename to media/module/bufferpool/1.0/vts/OWNERS
diff --git a/media/bufferpool/1.0/vts/allocator.cpp b/media/module/bufferpool/1.0/vts/allocator.cpp
similarity index 100%
rename from media/bufferpool/1.0/vts/allocator.cpp
rename to media/module/bufferpool/1.0/vts/allocator.cpp
diff --git a/media/bufferpool/1.0/vts/allocator.h b/media/module/bufferpool/1.0/vts/allocator.h
similarity index 100%
rename from media/bufferpool/1.0/vts/allocator.h
rename to media/module/bufferpool/1.0/vts/allocator.h
diff --git a/media/bufferpool/1.0/vts/multi.cpp b/media/module/bufferpool/1.0/vts/multi.cpp
similarity index 100%
rename from media/bufferpool/1.0/vts/multi.cpp
rename to media/module/bufferpool/1.0/vts/multi.cpp
diff --git a/media/bufferpool/1.0/vts/single.cpp b/media/module/bufferpool/1.0/vts/single.cpp
similarity index 100%
rename from media/bufferpool/1.0/vts/single.cpp
rename to media/module/bufferpool/1.0/vts/single.cpp
diff --git a/media/bufferpool/2.0/Accessor.cpp b/media/module/bufferpool/2.0/Accessor.cpp
similarity index 100%
rename from media/bufferpool/2.0/Accessor.cpp
rename to media/module/bufferpool/2.0/Accessor.cpp
diff --git a/media/bufferpool/2.0/Accessor.h b/media/module/bufferpool/2.0/Accessor.h
similarity index 100%
rename from media/bufferpool/2.0/Accessor.h
rename to media/module/bufferpool/2.0/Accessor.h
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/module/bufferpool/2.0/AccessorImpl.cpp
similarity index 100%
rename from media/bufferpool/2.0/AccessorImpl.cpp
rename to media/module/bufferpool/2.0/AccessorImpl.cpp
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/module/bufferpool/2.0/AccessorImpl.h
similarity index 100%
rename from media/bufferpool/2.0/AccessorImpl.h
rename to media/module/bufferpool/2.0/AccessorImpl.h
diff --git a/media/bufferpool/2.0/Android.bp b/media/module/bufferpool/2.0/Android.bp
similarity index 100%
rename from media/bufferpool/2.0/Android.bp
rename to media/module/bufferpool/2.0/Android.bp
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/module/bufferpool/2.0/BufferPoolClient.cpp
similarity index 100%
rename from media/bufferpool/2.0/BufferPoolClient.cpp
rename to media/module/bufferpool/2.0/BufferPoolClient.cpp
diff --git a/media/bufferpool/2.0/BufferPoolClient.h b/media/module/bufferpool/2.0/BufferPoolClient.h
similarity index 100%
rename from media/bufferpool/2.0/BufferPoolClient.h
rename to media/module/bufferpool/2.0/BufferPoolClient.h
diff --git a/media/bufferpool/2.0/BufferStatus.cpp b/media/module/bufferpool/2.0/BufferStatus.cpp
similarity index 100%
rename from media/bufferpool/2.0/BufferStatus.cpp
rename to media/module/bufferpool/2.0/BufferStatus.cpp
diff --git a/media/bufferpool/2.0/BufferStatus.h b/media/module/bufferpool/2.0/BufferStatus.h
similarity index 100%
rename from media/bufferpool/2.0/BufferStatus.h
rename to media/module/bufferpool/2.0/BufferStatus.h
diff --git a/media/bufferpool/2.0/ClientManager.cpp b/media/module/bufferpool/2.0/ClientManager.cpp
similarity index 100%
rename from media/bufferpool/2.0/ClientManager.cpp
rename to media/module/bufferpool/2.0/ClientManager.cpp
diff --git a/media/bufferpool/2.0/Connection.cpp b/media/module/bufferpool/2.0/Connection.cpp
similarity index 100%
rename from media/bufferpool/2.0/Connection.cpp
rename to media/module/bufferpool/2.0/Connection.cpp
diff --git a/media/bufferpool/2.0/Connection.h b/media/module/bufferpool/2.0/Connection.h
similarity index 100%
rename from media/bufferpool/2.0/Connection.h
rename to media/module/bufferpool/2.0/Connection.h
diff --git a/media/bufferpool/2.0/Observer.cpp b/media/module/bufferpool/2.0/Observer.cpp
similarity index 100%
rename from media/bufferpool/2.0/Observer.cpp
rename to media/module/bufferpool/2.0/Observer.cpp
diff --git a/media/bufferpool/2.0/Observer.h b/media/module/bufferpool/2.0/Observer.h
similarity index 100%
rename from media/bufferpool/2.0/Observer.h
rename to media/module/bufferpool/2.0/Observer.h
diff --git a/media/bufferpool/2.0/TEST_MAPPING b/media/module/bufferpool/2.0/TEST_MAPPING
similarity index 100%
rename from media/bufferpool/2.0/TEST_MAPPING
rename to media/module/bufferpool/2.0/TEST_MAPPING
diff --git a/media/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h b/media/module/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h
similarity index 100%
rename from media/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h
rename to media/module/bufferpool/2.0/include/bufferpool/BufferPoolTypes.h
diff --git a/media/bufferpool/2.0/include/bufferpool/ClientManager.h b/media/module/bufferpool/2.0/include/bufferpool/ClientManager.h
similarity index 100%
rename from media/bufferpool/2.0/include/bufferpool/ClientManager.h
rename to media/module/bufferpool/2.0/include/bufferpool/ClientManager.h
diff --git a/media/bufferpool/2.0/tests/Android.bp b/media/module/bufferpool/2.0/tests/Android.bp
similarity index 100%
rename from media/bufferpool/2.0/tests/Android.bp
rename to media/module/bufferpool/2.0/tests/Android.bp
diff --git a/media/bufferpool/2.0/tests/AndroidTest.xml b/media/module/bufferpool/2.0/tests/AndroidTest.xml
similarity index 100%
rename from media/bufferpool/2.0/tests/AndroidTest.xml
rename to media/module/bufferpool/2.0/tests/AndroidTest.xml
diff --git a/media/bufferpool/2.0/tests/BufferpoolUnitTest.cpp b/media/module/bufferpool/2.0/tests/BufferpoolUnitTest.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/BufferpoolUnitTest.cpp
rename to media/module/bufferpool/2.0/tests/BufferpoolUnitTest.cpp
diff --git a/media/bufferpool/2.0/tests/OWNERS b/media/module/bufferpool/2.0/tests/OWNERS
similarity index 100%
rename from media/bufferpool/2.0/tests/OWNERS
rename to media/module/bufferpool/2.0/tests/OWNERS
diff --git a/media/bufferpool/2.0/tests/README.md b/media/module/bufferpool/2.0/tests/README.md
similarity index 100%
rename from media/bufferpool/2.0/tests/README.md
rename to media/module/bufferpool/2.0/tests/README.md
diff --git a/media/bufferpool/2.0/tests/allocator.cpp b/media/module/bufferpool/2.0/tests/allocator.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/allocator.cpp
rename to media/module/bufferpool/2.0/tests/allocator.cpp
diff --git a/media/bufferpool/2.0/tests/allocator.h b/media/module/bufferpool/2.0/tests/allocator.h
similarity index 100%
rename from media/bufferpool/2.0/tests/allocator.h
rename to media/module/bufferpool/2.0/tests/allocator.h
diff --git a/media/bufferpool/2.0/tests/cond.cpp b/media/module/bufferpool/2.0/tests/cond.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/cond.cpp
rename to media/module/bufferpool/2.0/tests/cond.cpp
diff --git a/media/bufferpool/2.0/tests/multi.cpp b/media/module/bufferpool/2.0/tests/multi.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/multi.cpp
rename to media/module/bufferpool/2.0/tests/multi.cpp
diff --git a/media/bufferpool/2.0/tests/single.cpp b/media/module/bufferpool/2.0/tests/single.cpp
similarity index 100%
rename from media/bufferpool/2.0/tests/single.cpp
rename to media/module/bufferpool/2.0/tests/single.cpp
diff --git a/media/codecs/amrnb/TEST_MAPPING b/media/module/codecs/amrnb/TEST_MAPPING
similarity index 100%
rename from media/codecs/amrnb/TEST_MAPPING
rename to media/module/codecs/amrnb/TEST_MAPPING
diff --git a/media/codecs/amrnb/common/Android.bp b/media/module/codecs/amrnb/common/Android.bp
similarity index 100%
rename from media/codecs/amrnb/common/Android.bp
rename to media/module/codecs/amrnb/common/Android.bp
diff --git a/media/codecs/amrnb/common/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrnb/common/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrnb/common/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrnb/common/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrnb/common/NOTICE b/media/module/codecs/amrnb/common/NOTICE
similarity index 100%
rename from media/codecs/amrnb/common/NOTICE
rename to media/module/codecs/amrnb/common/NOTICE
diff --git a/media/codecs/amrnb/common/include/abs_s.h b/media/module/codecs/amrnb/common/include/abs_s.h
similarity index 100%
rename from media/codecs/amrnb/common/include/abs_s.h
rename to media/module/codecs/amrnb/common/include/abs_s.h
diff --git a/media/codecs/amrnb/common/include/add.h b/media/module/codecs/amrnb/common/include/add.h
similarity index 100%
rename from media/codecs/amrnb/common/include/add.h
rename to media/module/codecs/amrnb/common/include/add.h
diff --git a/media/codecs/amrnb/common/include/az_lsp.h b/media/module/codecs/amrnb/common/include/az_lsp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/az_lsp.h
rename to media/module/codecs/amrnb/common/include/az_lsp.h
diff --git a/media/codecs/amrnb/common/include/basic_op.h b/media/module/codecs/amrnb/common/include/basic_op.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op.h
rename to media/module/codecs/amrnb/common/include/basic_op.h
diff --git a/media/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h b/media/module/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
rename to media/module/codecs/amrnb/common/include/basic_op_arm_gcc_v5.h
diff --git a/media/codecs/amrnb/common/include/basic_op_arm_v5.h b/media/module/codecs/amrnb/common/include/basic_op_arm_v5.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op_arm_v5.h
rename to media/module/codecs/amrnb/common/include/basic_op_arm_v5.h
diff --git a/media/codecs/amrnb/common/include/basic_op_c_equivalent.h b/media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basic_op_c_equivalent.h
rename to media/module/codecs/amrnb/common/include/basic_op_c_equivalent.h
diff --git a/media/codecs/amrnb/common/include/basicop_malloc.h b/media/module/codecs/amrnb/common/include/basicop_malloc.h
similarity index 100%
rename from media/codecs/amrnb/common/include/basicop_malloc.h
rename to media/module/codecs/amrnb/common/include/basicop_malloc.h
diff --git a/media/codecs/amrnb/common/include/bitno_tab.h b/media/module/codecs/amrnb/common/include/bitno_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/bitno_tab.h
rename to media/module/codecs/amrnb/common/include/bitno_tab.h
diff --git a/media/codecs/amrnb/common/include/bitreorder_tab.h b/media/module/codecs/amrnb/common/include/bitreorder_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/bitreorder_tab.h
rename to media/module/codecs/amrnb/common/include/bitreorder_tab.h
diff --git a/media/codecs/amrnb/common/include/bits2prm.h b/media/module/codecs/amrnb/common/include/bits2prm.h
similarity index 100%
rename from media/codecs/amrnb/common/include/bits2prm.h
rename to media/module/codecs/amrnb/common/include/bits2prm.h
diff --git a/media/codecs/amrnb/common/include/cnst.h b/media/module/codecs/amrnb/common/include/cnst.h
similarity index 100%
rename from media/codecs/amrnb/common/include/cnst.h
rename to media/module/codecs/amrnb/common/include/cnst.h
diff --git a/media/codecs/amrnb/common/include/cnst_vad.h b/media/module/codecs/amrnb/common/include/cnst_vad.h
similarity index 100%
rename from media/codecs/amrnb/common/include/cnst_vad.h
rename to media/module/codecs/amrnb/common/include/cnst_vad.h
diff --git a/media/codecs/amrnb/common/include/copy.h b/media/module/codecs/amrnb/common/include/copy.h
similarity index 100%
rename from media/codecs/amrnb/common/include/copy.h
rename to media/module/codecs/amrnb/common/include/copy.h
diff --git a/media/codecs/amrnb/common/include/d_gain_c.h b/media/module/codecs/amrnb/common/include/d_gain_c.h
similarity index 100%
rename from media/codecs/amrnb/common/include/d_gain_c.h
rename to media/module/codecs/amrnb/common/include/d_gain_c.h
diff --git a/media/codecs/amrnb/common/include/d_gain_p.h b/media/module/codecs/amrnb/common/include/d_gain_p.h
similarity index 100%
rename from media/codecs/amrnb/common/include/d_gain_p.h
rename to media/module/codecs/amrnb/common/include/d_gain_p.h
diff --git a/media/codecs/amrnb/common/include/d_plsf.h b/media/module/codecs/amrnb/common/include/d_plsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/d_plsf.h
rename to media/module/codecs/amrnb/common/include/d_plsf.h
diff --git a/media/codecs/amrnb/common/include/div_32.h b/media/module/codecs/amrnb/common/include/div_32.h
similarity index 100%
rename from media/codecs/amrnb/common/include/div_32.h
rename to media/module/codecs/amrnb/common/include/div_32.h
diff --git a/media/codecs/amrnb/common/include/div_s.h b/media/module/codecs/amrnb/common/include/div_s.h
similarity index 100%
rename from media/codecs/amrnb/common/include/div_s.h
rename to media/module/codecs/amrnb/common/include/div_s.h
diff --git a/media/codecs/amrnb/common/include/dtx_common_def.h b/media/module/codecs/amrnb/common/include/dtx_common_def.h
similarity index 100%
rename from media/codecs/amrnb/common/include/dtx_common_def.h
rename to media/module/codecs/amrnb/common/include/dtx_common_def.h
diff --git a/media/codecs/amrnb/common/include/extract_h.h b/media/module/codecs/amrnb/common/include/extract_h.h
similarity index 100%
rename from media/codecs/amrnb/common/include/extract_h.h
rename to media/module/codecs/amrnb/common/include/extract_h.h
diff --git a/media/codecs/amrnb/common/include/extract_l.h b/media/module/codecs/amrnb/common/include/extract_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/extract_l.h
rename to media/module/codecs/amrnb/common/include/extract_l.h
diff --git a/media/codecs/amrnb/common/include/frame.h b/media/module/codecs/amrnb/common/include/frame.h
similarity index 100%
rename from media/codecs/amrnb/common/include/frame.h
rename to media/module/codecs/amrnb/common/include/frame.h
diff --git a/media/codecs/amrnb/common/include/frame_type_3gpp.h b/media/module/codecs/amrnb/common/include/frame_type_3gpp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/frame_type_3gpp.h
rename to media/module/codecs/amrnb/common/include/frame_type_3gpp.h
diff --git a/media/codecs/amrnb/common/include/gc_pred.h b/media/module/codecs/amrnb/common/include/gc_pred.h
similarity index 100%
rename from media/codecs/amrnb/common/include/gc_pred.h
rename to media/module/codecs/amrnb/common/include/gc_pred.h
diff --git a/media/codecs/amrnb/common/include/gmed_n.h b/media/module/codecs/amrnb/common/include/gmed_n.h
similarity index 100%
rename from media/codecs/amrnb/common/include/gmed_n.h
rename to media/module/codecs/amrnb/common/include/gmed_n.h
diff --git a/media/codecs/amrnb/common/include/gsm_amr_typedefs.h b/media/module/codecs/amrnb/common/include/gsm_amr_typedefs.h
similarity index 100%
rename from media/codecs/amrnb/common/include/gsm_amr_typedefs.h
rename to media/module/codecs/amrnb/common/include/gsm_amr_typedefs.h
diff --git a/media/codecs/amrnb/common/include/int_lpc.h b/media/module/codecs/amrnb/common/include/int_lpc.h
similarity index 100%
rename from media/codecs/amrnb/common/include/int_lpc.h
rename to media/module/codecs/amrnb/common/include/int_lpc.h
diff --git a/media/codecs/amrnb/common/include/int_lsf.h b/media/module/codecs/amrnb/common/include/int_lsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/int_lsf.h
rename to media/module/codecs/amrnb/common/include/int_lsf.h
diff --git a/media/codecs/amrnb/common/include/inv_sqrt.h b/media/module/codecs/amrnb/common/include/inv_sqrt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/inv_sqrt.h
rename to media/module/codecs/amrnb/common/include/inv_sqrt.h
diff --git a/media/codecs/amrnb/common/include/l_abs.h b/media/module/codecs/amrnb/common/include/l_abs.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_abs.h
rename to media/module/codecs/amrnb/common/include/l_abs.h
diff --git a/media/codecs/amrnb/common/include/l_add.h b/media/module/codecs/amrnb/common/include/l_add.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_add.h
rename to media/module/codecs/amrnb/common/include/l_add.h
diff --git a/media/codecs/amrnb/common/include/l_add_c.h b/media/module/codecs/amrnb/common/include/l_add_c.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_add_c.h
rename to media/module/codecs/amrnb/common/include/l_add_c.h
diff --git a/media/codecs/amrnb/common/include/l_comp.h b/media/module/codecs/amrnb/common/include/l_comp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_comp.h
rename to media/module/codecs/amrnb/common/include/l_comp.h
diff --git a/media/codecs/amrnb/common/include/l_deposit_h.h b/media/module/codecs/amrnb/common/include/l_deposit_h.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_deposit_h.h
rename to media/module/codecs/amrnb/common/include/l_deposit_h.h
diff --git a/media/codecs/amrnb/common/include/l_deposit_l.h b/media/module/codecs/amrnb/common/include/l_deposit_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_deposit_l.h
rename to media/module/codecs/amrnb/common/include/l_deposit_l.h
diff --git a/media/codecs/amrnb/common/include/l_extract.h b/media/module/codecs/amrnb/common/include/l_extract.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_extract.h
rename to media/module/codecs/amrnb/common/include/l_extract.h
diff --git a/media/codecs/amrnb/common/include/l_mac.h b/media/module/codecs/amrnb/common/include/l_mac.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_mac.h
rename to media/module/codecs/amrnb/common/include/l_mac.h
diff --git a/media/codecs/amrnb/common/include/l_msu.h b/media/module/codecs/amrnb/common/include/l_msu.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_msu.h
rename to media/module/codecs/amrnb/common/include/l_msu.h
diff --git a/media/codecs/amrnb/common/include/l_mult.h b/media/module/codecs/amrnb/common/include/l_mult.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_mult.h
rename to media/module/codecs/amrnb/common/include/l_mult.h
diff --git a/media/codecs/amrnb/common/include/l_negate.h b/media/module/codecs/amrnb/common/include/l_negate.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_negate.h
rename to media/module/codecs/amrnb/common/include/l_negate.h
diff --git a/media/codecs/amrnb/common/include/l_shl.h b/media/module/codecs/amrnb/common/include/l_shl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_shl.h
rename to media/module/codecs/amrnb/common/include/l_shl.h
diff --git a/media/codecs/amrnb/common/include/l_shr.h b/media/module/codecs/amrnb/common/include/l_shr.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_shr.h
rename to media/module/codecs/amrnb/common/include/l_shr.h
diff --git a/media/codecs/amrnb/common/include/l_shr_r.h b/media/module/codecs/amrnb/common/include/l_shr_r.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_shr_r.h
rename to media/module/codecs/amrnb/common/include/l_shr_r.h
diff --git a/media/codecs/amrnb/common/include/l_sub.h b/media/module/codecs/amrnb/common/include/l_sub.h
similarity index 100%
rename from media/codecs/amrnb/common/include/l_sub.h
rename to media/module/codecs/amrnb/common/include/l_sub.h
diff --git a/media/codecs/amrnb/common/include/log2.h b/media/module/codecs/amrnb/common/include/log2.h
similarity index 100%
rename from media/codecs/amrnb/common/include/log2.h
rename to media/module/codecs/amrnb/common/include/log2.h
diff --git a/media/codecs/amrnb/common/include/log2_norm.h b/media/module/codecs/amrnb/common/include/log2_norm.h
similarity index 100%
rename from media/codecs/amrnb/common/include/log2_norm.h
rename to media/module/codecs/amrnb/common/include/log2_norm.h
diff --git a/media/codecs/amrnb/common/include/lsfwt.h b/media/module/codecs/amrnb/common/include/lsfwt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsfwt.h
rename to media/module/codecs/amrnb/common/include/lsfwt.h
diff --git a/media/codecs/amrnb/common/include/lsp.h b/media/module/codecs/amrnb/common/include/lsp.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp.h
rename to media/module/codecs/amrnb/common/include/lsp.h
diff --git a/media/codecs/amrnb/common/include/lsp_az.h b/media/module/codecs/amrnb/common/include/lsp_az.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp_az.h
rename to media/module/codecs/amrnb/common/include/lsp_az.h
diff --git a/media/codecs/amrnb/common/include/lsp_lsf.h b/media/module/codecs/amrnb/common/include/lsp_lsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp_lsf.h
rename to media/module/codecs/amrnb/common/include/lsp_lsf.h
diff --git a/media/codecs/amrnb/common/include/lsp_tab.h b/media/module/codecs/amrnb/common/include/lsp_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/lsp_tab.h
rename to media/module/codecs/amrnb/common/include/lsp_tab.h
diff --git a/media/codecs/amrnb/common/include/mac_32.h b/media/module/codecs/amrnb/common/include/mac_32.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mac_32.h
rename to media/module/codecs/amrnb/common/include/mac_32.h
diff --git a/media/codecs/amrnb/common/include/mode.h b/media/module/codecs/amrnb/common/include/mode.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mode.h
rename to media/module/codecs/amrnb/common/include/mode.h
diff --git a/media/codecs/amrnb/common/include/mpy_32.h b/media/module/codecs/amrnb/common/include/mpy_32.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mpy_32.h
rename to media/module/codecs/amrnb/common/include/mpy_32.h
diff --git a/media/codecs/amrnb/common/include/mpy_32_16.h b/media/module/codecs/amrnb/common/include/mpy_32_16.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mpy_32_16.h
rename to media/module/codecs/amrnb/common/include/mpy_32_16.h
diff --git a/media/codecs/amrnb/common/include/mult.h b/media/module/codecs/amrnb/common/include/mult.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mult.h
rename to media/module/codecs/amrnb/common/include/mult.h
diff --git a/media/codecs/amrnb/common/include/mult_r.h b/media/module/codecs/amrnb/common/include/mult_r.h
similarity index 100%
rename from media/codecs/amrnb/common/include/mult_r.h
rename to media/module/codecs/amrnb/common/include/mult_r.h
diff --git a/media/codecs/amrnb/common/include/n_proc.h b/media/module/codecs/amrnb/common/include/n_proc.h
similarity index 100%
rename from media/codecs/amrnb/common/include/n_proc.h
rename to media/module/codecs/amrnb/common/include/n_proc.h
diff --git a/media/codecs/amrnb/common/include/negate.h b/media/module/codecs/amrnb/common/include/negate.h
similarity index 100%
rename from media/codecs/amrnb/common/include/negate.h
rename to media/module/codecs/amrnb/common/include/negate.h
diff --git a/media/codecs/amrnb/common/include/norm_l.h b/media/module/codecs/amrnb/common/include/norm_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/norm_l.h
rename to media/module/codecs/amrnb/common/include/norm_l.h
diff --git a/media/codecs/amrnb/common/include/norm_s.h b/media/module/codecs/amrnb/common/include/norm_s.h
similarity index 100%
rename from media/codecs/amrnb/common/include/norm_s.h
rename to media/module/codecs/amrnb/common/include/norm_s.h
diff --git a/media/codecs/amrnb/common/include/oper_32b.h b/media/module/codecs/amrnb/common/include/oper_32b.h
similarity index 100%
rename from media/codecs/amrnb/common/include/oper_32b.h
rename to media/module/codecs/amrnb/common/include/oper_32b.h
diff --git a/media/codecs/amrnb/common/include/p_ol_wgh.h b/media/module/codecs/amrnb/common/include/p_ol_wgh.h
similarity index 100%
rename from media/codecs/amrnb/common/include/p_ol_wgh.h
rename to media/module/codecs/amrnb/common/include/p_ol_wgh.h
diff --git a/media/codecs/amrnb/common/include/pow2.h b/media/module/codecs/amrnb/common/include/pow2.h
similarity index 100%
rename from media/codecs/amrnb/common/include/pow2.h
rename to media/module/codecs/amrnb/common/include/pow2.h
diff --git a/media/codecs/amrnb/common/include/pred_lt.h b/media/module/codecs/amrnb/common/include/pred_lt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/pred_lt.h
rename to media/module/codecs/amrnb/common/include/pred_lt.h
diff --git a/media/codecs/amrnb/common/include/q_plsf.h b/media/module/codecs/amrnb/common/include/q_plsf.h
similarity index 100%
rename from media/codecs/amrnb/common/include/q_plsf.h
rename to media/module/codecs/amrnb/common/include/q_plsf.h
diff --git a/media/codecs/amrnb/common/include/q_plsf_3_tbl.h b/media/module/codecs/amrnb/common/include/q_plsf_3_tbl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/q_plsf_3_tbl.h
rename to media/module/codecs/amrnb/common/include/q_plsf_3_tbl.h
diff --git a/media/codecs/amrnb/common/include/q_plsf_5_tbl.h b/media/module/codecs/amrnb/common/include/q_plsf_5_tbl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/q_plsf_5_tbl.h
rename to media/module/codecs/amrnb/common/include/q_plsf_5_tbl.h
diff --git a/media/codecs/amrnb/common/include/qgain475_tab.h b/media/module/codecs/amrnb/common/include/qgain475_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/qgain475_tab.h
rename to media/module/codecs/amrnb/common/include/qgain475_tab.h
diff --git a/media/codecs/amrnb/common/include/qua_gain.h b/media/module/codecs/amrnb/common/include/qua_gain.h
similarity index 100%
rename from media/codecs/amrnb/common/include/qua_gain.h
rename to media/module/codecs/amrnb/common/include/qua_gain.h
diff --git a/media/codecs/amrnb/common/include/qua_gain_tbl.h b/media/module/codecs/amrnb/common/include/qua_gain_tbl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/qua_gain_tbl.h
rename to media/module/codecs/amrnb/common/include/qua_gain_tbl.h
diff --git a/media/codecs/amrnb/common/include/reorder.h b/media/module/codecs/amrnb/common/include/reorder.h
similarity index 100%
rename from media/codecs/amrnb/common/include/reorder.h
rename to media/module/codecs/amrnb/common/include/reorder.h
diff --git a/media/codecs/amrnb/common/include/residu.h b/media/module/codecs/amrnb/common/include/residu.h
similarity index 100%
rename from media/codecs/amrnb/common/include/residu.h
rename to media/module/codecs/amrnb/common/include/residu.h
diff --git a/media/codecs/amrnb/common/include/reverse_bits.h b/media/module/codecs/amrnb/common/include/reverse_bits.h
similarity index 100%
rename from media/codecs/amrnb/common/include/reverse_bits.h
rename to media/module/codecs/amrnb/common/include/reverse_bits.h
diff --git a/media/codecs/amrnb/common/include/round.h b/media/module/codecs/amrnb/common/include/round.h
similarity index 100%
rename from media/codecs/amrnb/common/include/round.h
rename to media/module/codecs/amrnb/common/include/round.h
diff --git a/media/codecs/amrnb/common/include/set_zero.h b/media/module/codecs/amrnb/common/include/set_zero.h
similarity index 100%
rename from media/codecs/amrnb/common/include/set_zero.h
rename to media/module/codecs/amrnb/common/include/set_zero.h
diff --git a/media/codecs/amrnb/common/include/shl.h b/media/module/codecs/amrnb/common/include/shl.h
similarity index 100%
rename from media/codecs/amrnb/common/include/shl.h
rename to media/module/codecs/amrnb/common/include/shl.h
diff --git a/media/codecs/amrnb/common/include/shr.h b/media/module/codecs/amrnb/common/include/shr.h
similarity index 100%
rename from media/codecs/amrnb/common/include/shr.h
rename to media/module/codecs/amrnb/common/include/shr.h
diff --git a/media/codecs/amrnb/common/include/shr_r.h b/media/module/codecs/amrnb/common/include/shr_r.h
similarity index 100%
rename from media/codecs/amrnb/common/include/shr_r.h
rename to media/module/codecs/amrnb/common/include/shr_r.h
diff --git a/media/codecs/amrnb/common/include/sqrt_l.h b/media/module/codecs/amrnb/common/include/sqrt_l.h
similarity index 100%
rename from media/codecs/amrnb/common/include/sqrt_l.h
rename to media/module/codecs/amrnb/common/include/sqrt_l.h
diff --git a/media/codecs/amrnb/common/include/sub.h b/media/module/codecs/amrnb/common/include/sub.h
similarity index 100%
rename from media/codecs/amrnb/common/include/sub.h
rename to media/module/codecs/amrnb/common/include/sub.h
diff --git a/media/codecs/amrnb/common/include/syn_filt.h b/media/module/codecs/amrnb/common/include/syn_filt.h
similarity index 100%
rename from media/codecs/amrnb/common/include/syn_filt.h
rename to media/module/codecs/amrnb/common/include/syn_filt.h
diff --git a/media/codecs/amrnb/common/include/typedef.h b/media/module/codecs/amrnb/common/include/typedef.h
similarity index 100%
rename from media/codecs/amrnb/common/include/typedef.h
rename to media/module/codecs/amrnb/common/include/typedef.h
diff --git a/media/codecs/amrnb/common/include/vad.h b/media/module/codecs/amrnb/common/include/vad.h
similarity index 100%
rename from media/codecs/amrnb/common/include/vad.h
rename to media/module/codecs/amrnb/common/include/vad.h
diff --git a/media/codecs/amrnb/common/include/vad1.h b/media/module/codecs/amrnb/common/include/vad1.h
similarity index 100%
rename from media/codecs/amrnb/common/include/vad1.h
rename to media/module/codecs/amrnb/common/include/vad1.h
diff --git a/media/codecs/amrnb/common/include/vad2.h b/media/module/codecs/amrnb/common/include/vad2.h
similarity index 100%
rename from media/codecs/amrnb/common/include/vad2.h
rename to media/module/codecs/amrnb/common/include/vad2.h
diff --git a/media/codecs/amrnb/common/include/weight_a.h b/media/module/codecs/amrnb/common/include/weight_a.h
similarity index 100%
rename from media/codecs/amrnb/common/include/weight_a.h
rename to media/module/codecs/amrnb/common/include/weight_a.h
diff --git a/media/codecs/amrnb/common/include/window_tab.h b/media/module/codecs/amrnb/common/include/window_tab.h
similarity index 100%
rename from media/codecs/amrnb/common/include/window_tab.h
rename to media/module/codecs/amrnb/common/include/window_tab.h
diff --git a/media/codecs/amrnb/common/include/wmf_to_ets.h b/media/module/codecs/amrnb/common/include/wmf_to_ets.h
similarity index 100%
rename from media/codecs/amrnb/common/include/wmf_to_ets.h
rename to media/module/codecs/amrnb/common/include/wmf_to_ets.h
diff --git a/media/codecs/amrnb/common/src/add.cpp b/media/module/codecs/amrnb/common/src/add.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/add.cpp
rename to media/module/codecs/amrnb/common/src/add.cpp
diff --git a/media/codecs/amrnb/common/src/az_lsp.cpp b/media/module/codecs/amrnb/common/src/az_lsp.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/az_lsp.cpp
rename to media/module/codecs/amrnb/common/src/az_lsp.cpp
diff --git a/media/codecs/amrnb/common/src/bitno_tab.cpp b/media/module/codecs/amrnb/common/src/bitno_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/bitno_tab.cpp
rename to media/module/codecs/amrnb/common/src/bitno_tab.cpp
diff --git a/media/codecs/amrnb/common/src/bitreorder_tab.cpp b/media/module/codecs/amrnb/common/src/bitreorder_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/bitreorder_tab.cpp
rename to media/module/codecs/amrnb/common/src/bitreorder_tab.cpp
diff --git a/media/codecs/amrnb/common/src/bits2prm.cpp b/media/module/codecs/amrnb/common/src/bits2prm.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/bits2prm.cpp
rename to media/module/codecs/amrnb/common/src/bits2prm.cpp
diff --git a/media/codecs/amrnb/common/src/c2_9pf_tab.cpp b/media/module/codecs/amrnb/common/src/c2_9pf_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/c2_9pf_tab.cpp
rename to media/module/codecs/amrnb/common/src/c2_9pf_tab.cpp
diff --git a/media/codecs/amrnb/common/src/copy.cpp b/media/module/codecs/amrnb/common/src/copy.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/copy.cpp
rename to media/module/codecs/amrnb/common/src/copy.cpp
diff --git a/media/codecs/amrnb/common/src/div_32.cpp b/media/module/codecs/amrnb/common/src/div_32.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/div_32.cpp
rename to media/module/codecs/amrnb/common/src/div_32.cpp
diff --git a/media/codecs/amrnb/common/src/div_s.cpp b/media/module/codecs/amrnb/common/src/div_s.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/div_s.cpp
rename to media/module/codecs/amrnb/common/src/div_s.cpp
diff --git a/media/codecs/amrnb/common/src/extract_h.cpp b/media/module/codecs/amrnb/common/src/extract_h.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/extract_h.cpp
rename to media/module/codecs/amrnb/common/src/extract_h.cpp
diff --git a/media/codecs/amrnb/common/src/extract_l.cpp b/media/module/codecs/amrnb/common/src/extract_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/extract_l.cpp
rename to media/module/codecs/amrnb/common/src/extract_l.cpp
diff --git a/media/codecs/amrnb/common/src/gains_tbl.cpp b/media/module/codecs/amrnb/common/src/gains_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gains_tbl.cpp
rename to media/module/codecs/amrnb/common/src/gains_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/gc_pred.cpp b/media/module/codecs/amrnb/common/src/gc_pred.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gc_pred.cpp
rename to media/module/codecs/amrnb/common/src/gc_pred.cpp
diff --git a/media/codecs/amrnb/common/src/gmed_n.cpp b/media/module/codecs/amrnb/common/src/gmed_n.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gmed_n.cpp
rename to media/module/codecs/amrnb/common/src/gmed_n.cpp
diff --git a/media/codecs/amrnb/common/src/gray_tbl.cpp b/media/module/codecs/amrnb/common/src/gray_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/gray_tbl.cpp
rename to media/module/codecs/amrnb/common/src/gray_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/grid_tbl.cpp b/media/module/codecs/amrnb/common/src/grid_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/grid_tbl.cpp
rename to media/module/codecs/amrnb/common/src/grid_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/int_lpc.cpp b/media/module/codecs/amrnb/common/src/int_lpc.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/int_lpc.cpp
rename to media/module/codecs/amrnb/common/src/int_lpc.cpp
diff --git a/media/codecs/amrnb/common/src/inv_sqrt.cpp b/media/module/codecs/amrnb/common/src/inv_sqrt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/inv_sqrt.cpp
rename to media/module/codecs/amrnb/common/src/inv_sqrt.cpp
diff --git a/media/codecs/amrnb/common/src/inv_sqrt_tbl.cpp b/media/module/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
rename to media/module/codecs/amrnb/common/src/inv_sqrt_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/l_abs.cpp b/media/module/codecs/amrnb/common/src/l_abs.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_abs.cpp
rename to media/module/codecs/amrnb/common/src/l_abs.cpp
diff --git a/media/codecs/amrnb/common/src/l_deposit_h.cpp b/media/module/codecs/amrnb/common/src/l_deposit_h.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_deposit_h.cpp
rename to media/module/codecs/amrnb/common/src/l_deposit_h.cpp
diff --git a/media/codecs/amrnb/common/src/l_deposit_l.cpp b/media/module/codecs/amrnb/common/src/l_deposit_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_deposit_l.cpp
rename to media/module/codecs/amrnb/common/src/l_deposit_l.cpp
diff --git a/media/codecs/amrnb/common/src/l_shr_r.cpp b/media/module/codecs/amrnb/common/src/l_shr_r.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/l_shr_r.cpp
rename to media/module/codecs/amrnb/common/src/l_shr_r.cpp
diff --git a/media/codecs/amrnb/common/src/log2.cpp b/media/module/codecs/amrnb/common/src/log2.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/log2.cpp
rename to media/module/codecs/amrnb/common/src/log2.cpp
diff --git a/media/codecs/amrnb/common/src/log2_norm.cpp b/media/module/codecs/amrnb/common/src/log2_norm.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/log2_norm.cpp
rename to media/module/codecs/amrnb/common/src/log2_norm.cpp
diff --git a/media/codecs/amrnb/common/src/log2_tbl.cpp b/media/module/codecs/amrnb/common/src/log2_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/log2_tbl.cpp
rename to media/module/codecs/amrnb/common/src/log2_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/lsfwt.cpp b/media/module/codecs/amrnb/common/src/lsfwt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsfwt.cpp
rename to media/module/codecs/amrnb/common/src/lsfwt.cpp
diff --git a/media/codecs/amrnb/common/src/lsp.cpp b/media/module/codecs/amrnb/common/src/lsp.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp.cpp
rename to media/module/codecs/amrnb/common/src/lsp.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_az.cpp b/media/module/codecs/amrnb/common/src/lsp_az.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_az.cpp
rename to media/module/codecs/amrnb/common/src/lsp_az.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_lsf.cpp b/media/module/codecs/amrnb/common/src/lsp_lsf.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_lsf.cpp
rename to media/module/codecs/amrnb/common/src/lsp_lsf.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_lsf_tbl.cpp b/media/module/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
rename to media/module/codecs/amrnb/common/src/lsp_lsf_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/lsp_tab.cpp b/media/module/codecs/amrnb/common/src/lsp_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/lsp_tab.cpp
rename to media/module/codecs/amrnb/common/src/lsp_tab.cpp
diff --git a/media/codecs/amrnb/common/src/mult_r.cpp b/media/module/codecs/amrnb/common/src/mult_r.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/mult_r.cpp
rename to media/module/codecs/amrnb/common/src/mult_r.cpp
diff --git a/media/codecs/amrnb/common/src/negate.cpp b/media/module/codecs/amrnb/common/src/negate.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/negate.cpp
rename to media/module/codecs/amrnb/common/src/negate.cpp
diff --git a/media/codecs/amrnb/common/src/norm_l.cpp b/media/module/codecs/amrnb/common/src/norm_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/norm_l.cpp
rename to media/module/codecs/amrnb/common/src/norm_l.cpp
diff --git a/media/codecs/amrnb/common/src/norm_s.cpp b/media/module/codecs/amrnb/common/src/norm_s.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/norm_s.cpp
rename to media/module/codecs/amrnb/common/src/norm_s.cpp
diff --git a/media/codecs/amrnb/common/src/ph_disp_tab.cpp b/media/module/codecs/amrnb/common/src/ph_disp_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/ph_disp_tab.cpp
rename to media/module/codecs/amrnb/common/src/ph_disp_tab.cpp
diff --git a/media/codecs/amrnb/common/src/pow2.cpp b/media/module/codecs/amrnb/common/src/pow2.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/pow2.cpp
rename to media/module/codecs/amrnb/common/src/pow2.cpp
diff --git a/media/codecs/amrnb/common/src/pow2_tbl.cpp b/media/module/codecs/amrnb/common/src/pow2_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/pow2_tbl.cpp
rename to media/module/codecs/amrnb/common/src/pow2_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/pred_lt.cpp b/media/module/codecs/amrnb/common/src/pred_lt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/pred_lt.cpp
rename to media/module/codecs/amrnb/common/src/pred_lt.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf.cpp b/media/module/codecs/amrnb/common/src/q_plsf.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_3.cpp b/media/module/codecs/amrnb/common/src/q_plsf_3.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_3.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_3.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_3_tbl.cpp b/media/module/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_3_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_5.cpp b/media/module/codecs/amrnb/common/src/q_plsf_5.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_5.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_5.cpp
diff --git a/media/codecs/amrnb/common/src/q_plsf_5_tbl.cpp b/media/module/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
rename to media/module/codecs/amrnb/common/src/q_plsf_5_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/qua_gain_tbl.cpp b/media/module/codecs/amrnb/common/src/qua_gain_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/qua_gain_tbl.cpp
rename to media/module/codecs/amrnb/common/src/qua_gain_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/reorder.cpp b/media/module/codecs/amrnb/common/src/reorder.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/reorder.cpp
rename to media/module/codecs/amrnb/common/src/reorder.cpp
diff --git a/media/codecs/amrnb/common/src/residu.cpp b/media/module/codecs/amrnb/common/src/residu.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/residu.cpp
rename to media/module/codecs/amrnb/common/src/residu.cpp
diff --git a/media/codecs/amrnb/common/src/round.cpp b/media/module/codecs/amrnb/common/src/round.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/round.cpp
rename to media/module/codecs/amrnb/common/src/round.cpp
diff --git a/media/codecs/amrnb/common/src/set_zero.cpp b/media/module/codecs/amrnb/common/src/set_zero.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/set_zero.cpp
rename to media/module/codecs/amrnb/common/src/set_zero.cpp
diff --git a/media/codecs/amrnb/common/src/shr.cpp b/media/module/codecs/amrnb/common/src/shr.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/shr.cpp
rename to media/module/codecs/amrnb/common/src/shr.cpp
diff --git a/media/codecs/amrnb/common/src/shr_r.cpp b/media/module/codecs/amrnb/common/src/shr_r.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/shr_r.cpp
rename to media/module/codecs/amrnb/common/src/shr_r.cpp
diff --git a/media/codecs/amrnb/common/src/sqrt_l.cpp b/media/module/codecs/amrnb/common/src/sqrt_l.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/sqrt_l.cpp
rename to media/module/codecs/amrnb/common/src/sqrt_l.cpp
diff --git a/media/codecs/amrnb/common/src/sqrt_l_tbl.cpp b/media/module/codecs/amrnb/common/src/sqrt_l_tbl.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/sqrt_l_tbl.cpp
rename to media/module/codecs/amrnb/common/src/sqrt_l_tbl.cpp
diff --git a/media/codecs/amrnb/common/src/sub.cpp b/media/module/codecs/amrnb/common/src/sub.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/sub.cpp
rename to media/module/codecs/amrnb/common/src/sub.cpp
diff --git a/media/codecs/amrnb/common/src/syn_filt.cpp b/media/module/codecs/amrnb/common/src/syn_filt.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/syn_filt.cpp
rename to media/module/codecs/amrnb/common/src/syn_filt.cpp
diff --git a/media/codecs/amrnb/common/src/vad1.cpp b/media/module/codecs/amrnb/common/src/vad1.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/vad1.cpp
rename to media/module/codecs/amrnb/common/src/vad1.cpp
diff --git a/media/codecs/amrnb/common/src/weight_a.cpp b/media/module/codecs/amrnb/common/src/weight_a.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/weight_a.cpp
rename to media/module/codecs/amrnb/common/src/weight_a.cpp
diff --git a/media/codecs/amrnb/common/src/window_tab.cpp b/media/module/codecs/amrnb/common/src/window_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/common/src/window_tab.cpp
rename to media/module/codecs/amrnb/common/src/window_tab.cpp
diff --git a/media/codecs/amrnb/dec/Android.bp b/media/module/codecs/amrnb/dec/Android.bp
similarity index 100%
rename from media/codecs/amrnb/dec/Android.bp
rename to media/module/codecs/amrnb/dec/Android.bp
diff --git a/media/codecs/amrnb/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrnb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrnb/dec/NOTICE b/media/module/codecs/amrnb/dec/NOTICE
similarity index 100%
rename from media/codecs/amrnb/dec/NOTICE
rename to media/module/codecs/amrnb/dec/NOTICE
diff --git a/media/codecs/amrnb/dec/src/a_refl.cpp b/media/module/codecs/amrnb/dec/src/a_refl.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/a_refl.cpp
rename to media/module/codecs/amrnb/dec/src/a_refl.cpp
diff --git a/media/codecs/amrnb/dec/src/a_refl.h b/media/module/codecs/amrnb/dec/src/a_refl.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/a_refl.h
rename to media/module/codecs/amrnb/dec/src/a_refl.h
diff --git a/media/codecs/amrnb/dec/src/agc.cpp b/media/module/codecs/amrnb/dec/src/agc.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/agc.cpp
rename to media/module/codecs/amrnb/dec/src/agc.cpp
diff --git a/media/codecs/amrnb/dec/src/agc.h b/media/module/codecs/amrnb/dec/src/agc.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/agc.h
rename to media/module/codecs/amrnb/dec/src/agc.h
diff --git a/media/codecs/amrnb/dec/src/amrdecode.cpp b/media/module/codecs/amrnb/dec/src/amrdecode.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/amrdecode.cpp
rename to media/module/codecs/amrnb/dec/src/amrdecode.cpp
diff --git a/media/codecs/amrnb/dec/src/amrdecode.h b/media/module/codecs/amrnb/dec/src/amrdecode.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/amrdecode.h
rename to media/module/codecs/amrnb/dec/src/amrdecode.h
diff --git a/media/codecs/amrnb/dec/src/b_cn_cod.cpp b/media/module/codecs/amrnb/dec/src/b_cn_cod.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/b_cn_cod.cpp
rename to media/module/codecs/amrnb/dec/src/b_cn_cod.cpp
diff --git a/media/codecs/amrnb/dec/src/b_cn_cod.h b/media/module/codecs/amrnb/dec/src/b_cn_cod.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/b_cn_cod.h
rename to media/module/codecs/amrnb/dec/src/b_cn_cod.h
diff --git a/media/codecs/amrnb/dec/src/bgnscd.cpp b/media/module/codecs/amrnb/dec/src/bgnscd.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/bgnscd.cpp
rename to media/module/codecs/amrnb/dec/src/bgnscd.cpp
diff --git a/media/codecs/amrnb/dec/src/bgnscd.h b/media/module/codecs/amrnb/dec/src/bgnscd.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/bgnscd.h
rename to media/module/codecs/amrnb/dec/src/bgnscd.h
diff --git a/media/codecs/amrnb/dec/src/c_g_aver.cpp b/media/module/codecs/amrnb/dec/src/c_g_aver.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/c_g_aver.cpp
rename to media/module/codecs/amrnb/dec/src/c_g_aver.cpp
diff --git a/media/codecs/amrnb/dec/src/c_g_aver.h b/media/module/codecs/amrnb/dec/src/c_g_aver.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/c_g_aver.h
rename to media/module/codecs/amrnb/dec/src/c_g_aver.h
diff --git a/media/codecs/amrnb/dec/src/d1035pf.cpp b/media/module/codecs/amrnb/dec/src/d1035pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d1035pf.cpp
rename to media/module/codecs/amrnb/dec/src/d1035pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d1035pf.h b/media/module/codecs/amrnb/dec/src/d1035pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d1035pf.h
rename to media/module/codecs/amrnb/dec/src/d1035pf.h
diff --git a/media/codecs/amrnb/dec/src/d2_11pf.cpp b/media/module/codecs/amrnb/dec/src/d2_11pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_11pf.cpp
rename to media/module/codecs/amrnb/dec/src/d2_11pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d2_11pf.h b/media/module/codecs/amrnb/dec/src/d2_11pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_11pf.h
rename to media/module/codecs/amrnb/dec/src/d2_11pf.h
diff --git a/media/codecs/amrnb/dec/src/d2_9pf.cpp b/media/module/codecs/amrnb/dec/src/d2_9pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_9pf.cpp
rename to media/module/codecs/amrnb/dec/src/d2_9pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d2_9pf.h b/media/module/codecs/amrnb/dec/src/d2_9pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d2_9pf.h
rename to media/module/codecs/amrnb/dec/src/d2_9pf.h
diff --git a/media/codecs/amrnb/dec/src/d3_14pf.cpp b/media/module/codecs/amrnb/dec/src/d3_14pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d3_14pf.cpp
rename to media/module/codecs/amrnb/dec/src/d3_14pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d3_14pf.h b/media/module/codecs/amrnb/dec/src/d3_14pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d3_14pf.h
rename to media/module/codecs/amrnb/dec/src/d3_14pf.h
diff --git a/media/codecs/amrnb/dec/src/d4_17pf.cpp b/media/module/codecs/amrnb/dec/src/d4_17pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d4_17pf.cpp
rename to media/module/codecs/amrnb/dec/src/d4_17pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d4_17pf.h b/media/module/codecs/amrnb/dec/src/d4_17pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d4_17pf.h
rename to media/module/codecs/amrnb/dec/src/d4_17pf.h
diff --git a/media/codecs/amrnb/dec/src/d8_31pf.cpp b/media/module/codecs/amrnb/dec/src/d8_31pf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d8_31pf.cpp
rename to media/module/codecs/amrnb/dec/src/d8_31pf.cpp
diff --git a/media/codecs/amrnb/dec/src/d8_31pf.h b/media/module/codecs/amrnb/dec/src/d8_31pf.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/d8_31pf.h
rename to media/module/codecs/amrnb/dec/src/d8_31pf.h
diff --git a/media/codecs/amrnb/dec/src/d_gain_c.cpp b/media/module/codecs/amrnb/dec/src/d_gain_c.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_gain_c.cpp
rename to media/module/codecs/amrnb/dec/src/d_gain_c.cpp
diff --git a/media/codecs/amrnb/dec/src/d_gain_p.cpp b/media/module/codecs/amrnb/dec/src/d_gain_p.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_gain_p.cpp
rename to media/module/codecs/amrnb/dec/src/d_gain_p.cpp
diff --git a/media/codecs/amrnb/dec/src/d_plsf.cpp b/media/module/codecs/amrnb/dec/src/d_plsf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_plsf.cpp
rename to media/module/codecs/amrnb/dec/src/d_plsf.cpp
diff --git a/media/codecs/amrnb/dec/src/d_plsf_3.cpp b/media/module/codecs/amrnb/dec/src/d_plsf_3.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_plsf_3.cpp
rename to media/module/codecs/amrnb/dec/src/d_plsf_3.cpp
diff --git a/media/codecs/amrnb/dec/src/d_plsf_5.cpp b/media/module/codecs/amrnb/dec/src/d_plsf_5.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/d_plsf_5.cpp
rename to media/module/codecs/amrnb/dec/src/d_plsf_5.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_amr.cpp b/media/module/codecs/amrnb/dec/src/dec_amr.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_amr.cpp
rename to media/module/codecs/amrnb/dec/src/dec_amr.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_amr.h b/media/module/codecs/amrnb/dec/src/dec_amr.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_amr.h
rename to media/module/codecs/amrnb/dec/src/dec_amr.h
diff --git a/media/codecs/amrnb/dec/src/dec_gain.cpp b/media/module/codecs/amrnb/dec/src/dec_gain.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_gain.cpp
rename to media/module/codecs/amrnb/dec/src/dec_gain.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_gain.h b/media/module/codecs/amrnb/dec/src/dec_gain.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_gain.h
rename to media/module/codecs/amrnb/dec/src/dec_gain.h
diff --git a/media/codecs/amrnb/dec/src/dec_input_format_tab.cpp b/media/module/codecs/amrnb/dec/src/dec_input_format_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_input_format_tab.cpp
rename to media/module/codecs/amrnb/dec/src/dec_input_format_tab.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_lag3.cpp b/media/module/codecs/amrnb/dec/src/dec_lag3.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag3.cpp
rename to media/module/codecs/amrnb/dec/src/dec_lag3.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_lag3.h b/media/module/codecs/amrnb/dec/src/dec_lag3.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag3.h
rename to media/module/codecs/amrnb/dec/src/dec_lag3.h
diff --git a/media/codecs/amrnb/dec/src/dec_lag6.cpp b/media/module/codecs/amrnb/dec/src/dec_lag6.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag6.cpp
rename to media/module/codecs/amrnb/dec/src/dec_lag6.cpp
diff --git a/media/codecs/amrnb/dec/src/dec_lag6.h b/media/module/codecs/amrnb/dec/src/dec_lag6.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dec_lag6.h
rename to media/module/codecs/amrnb/dec/src/dec_lag6.h
diff --git a/media/codecs/amrnb/dec/src/dtx_dec.cpp b/media/module/codecs/amrnb/dec/src/dtx_dec.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/dtx_dec.cpp
rename to media/module/codecs/amrnb/dec/src/dtx_dec.cpp
diff --git a/media/codecs/amrnb/dec/src/dtx_dec.h b/media/module/codecs/amrnb/dec/src/dtx_dec.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/dtx_dec.h
rename to media/module/codecs/amrnb/dec/src/dtx_dec.h
diff --git a/media/codecs/amrnb/dec/src/ec_gains.cpp b/media/module/codecs/amrnb/dec/src/ec_gains.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/ec_gains.cpp
rename to media/module/codecs/amrnb/dec/src/ec_gains.cpp
diff --git a/media/codecs/amrnb/dec/src/ec_gains.h b/media/module/codecs/amrnb/dec/src/ec_gains.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/ec_gains.h
rename to media/module/codecs/amrnb/dec/src/ec_gains.h
diff --git a/media/codecs/amrnb/dec/src/ex_ctrl.cpp b/media/module/codecs/amrnb/dec/src/ex_ctrl.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/ex_ctrl.cpp
rename to media/module/codecs/amrnb/dec/src/ex_ctrl.cpp
diff --git a/media/codecs/amrnb/dec/src/ex_ctrl.h b/media/module/codecs/amrnb/dec/src/ex_ctrl.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/ex_ctrl.h
rename to media/module/codecs/amrnb/dec/src/ex_ctrl.h
diff --git a/media/codecs/amrnb/dec/src/gsmamr_dec.h b/media/module/codecs/amrnb/dec/src/gsmamr_dec.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/gsmamr_dec.h
rename to media/module/codecs/amrnb/dec/src/gsmamr_dec.h
diff --git a/media/codecs/amrnb/dec/src/if2_to_ets.cpp b/media/module/codecs/amrnb/dec/src/if2_to_ets.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/if2_to_ets.cpp
rename to media/module/codecs/amrnb/dec/src/if2_to_ets.cpp
diff --git a/media/codecs/amrnb/dec/src/if2_to_ets.h b/media/module/codecs/amrnb/dec/src/if2_to_ets.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/if2_to_ets.h
rename to media/module/codecs/amrnb/dec/src/if2_to_ets.h
diff --git a/media/codecs/amrnb/dec/src/int_lsf.cpp b/media/module/codecs/amrnb/dec/src/int_lsf.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/int_lsf.cpp
rename to media/module/codecs/amrnb/dec/src/int_lsf.cpp
diff --git a/media/codecs/amrnb/dec/src/lsp_avg.cpp b/media/module/codecs/amrnb/dec/src/lsp_avg.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/lsp_avg.cpp
rename to media/module/codecs/amrnb/dec/src/lsp_avg.cpp
diff --git a/media/codecs/amrnb/dec/src/lsp_avg.h b/media/module/codecs/amrnb/dec/src/lsp_avg.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/lsp_avg.h
rename to media/module/codecs/amrnb/dec/src/lsp_avg.h
diff --git a/media/codecs/amrnb/dec/src/ph_disp.cpp b/media/module/codecs/amrnb/dec/src/ph_disp.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/ph_disp.cpp
rename to media/module/codecs/amrnb/dec/src/ph_disp.cpp
diff --git a/media/codecs/amrnb/dec/src/ph_disp.h b/media/module/codecs/amrnb/dec/src/ph_disp.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/ph_disp.h
rename to media/module/codecs/amrnb/dec/src/ph_disp.h
diff --git a/media/codecs/amrnb/dec/src/post_pro.cpp b/media/module/codecs/amrnb/dec/src/post_pro.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/post_pro.cpp
rename to media/module/codecs/amrnb/dec/src/post_pro.cpp
diff --git a/media/codecs/amrnb/dec/src/post_pro.h b/media/module/codecs/amrnb/dec/src/post_pro.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/post_pro.h
rename to media/module/codecs/amrnb/dec/src/post_pro.h
diff --git a/media/codecs/amrnb/dec/src/preemph.cpp b/media/module/codecs/amrnb/dec/src/preemph.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/preemph.cpp
rename to media/module/codecs/amrnb/dec/src/preemph.cpp
diff --git a/media/codecs/amrnb/dec/src/preemph.h b/media/module/codecs/amrnb/dec/src/preemph.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/preemph.h
rename to media/module/codecs/amrnb/dec/src/preemph.h
diff --git a/media/codecs/amrnb/dec/src/pstfilt.cpp b/media/module/codecs/amrnb/dec/src/pstfilt.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/pstfilt.cpp
rename to media/module/codecs/amrnb/dec/src/pstfilt.cpp
diff --git a/media/codecs/amrnb/dec/src/pstfilt.h b/media/module/codecs/amrnb/dec/src/pstfilt.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/pstfilt.h
rename to media/module/codecs/amrnb/dec/src/pstfilt.h
diff --git a/media/codecs/amrnb/dec/src/qgain475_tab.cpp b/media/module/codecs/amrnb/dec/src/qgain475_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/qgain475_tab.cpp
rename to media/module/codecs/amrnb/dec/src/qgain475_tab.cpp
diff --git a/media/codecs/amrnb/dec/src/sp_dec.cpp b/media/module/codecs/amrnb/dec/src/sp_dec.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/sp_dec.cpp
rename to media/module/codecs/amrnb/dec/src/sp_dec.cpp
diff --git a/media/codecs/amrnb/dec/src/sp_dec.h b/media/module/codecs/amrnb/dec/src/sp_dec.h
similarity index 100%
rename from media/codecs/amrnb/dec/src/sp_dec.h
rename to media/module/codecs/amrnb/dec/src/sp_dec.h
diff --git a/media/codecs/amrnb/dec/src/wmf_to_ets.cpp b/media/module/codecs/amrnb/dec/src/wmf_to_ets.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/src/wmf_to_ets.cpp
rename to media/module/codecs/amrnb/dec/src/wmf_to_ets.cpp
diff --git a/media/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h b/media/module/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
similarity index 100%
rename from media/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
rename to media/module/codecs/amrnb/dec/test/AmrnbDecTestEnvironment.h
diff --git a/media/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp b/media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
rename to media/module/codecs/amrnb/dec/test/AmrnbDecoderTest.cpp
diff --git a/media/codecs/amrnb/dec/test/Android.bp b/media/module/codecs/amrnb/dec/test/Android.bp
similarity index 90%
rename from media/codecs/amrnb/dec/test/Android.bp
rename to media/module/codecs/amrnb/dec/test/Android.bp
index 74258e0..de69cfc 100644
--- a/media/codecs/amrnb/dec/test/Android.bp
+++ b/media/module/codecs/amrnb/dec/test/Android.bp
@@ -58,4 +58,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/dec/test/AmrnbDecoderTest.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/amrnb/dec/test/AndroidTest.xml b/media/module/codecs/amrnb/dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrnb/dec/test/AndroidTest.xml
rename to media/module/codecs/amrnb/dec/test/AndroidTest.xml
diff --git a/media/codecs/amrnb/dec/test/README.md b/media/module/codecs/amrnb/dec/test/README.md
similarity index 100%
rename from media/codecs/amrnb/dec/test/README.md
rename to media/module/codecs/amrnb/dec/test/README.md
diff --git a/media/codecs/amrnb/dec/test/amrnbdec_test.cpp b/media/module/codecs/amrnb/dec/test/amrnbdec_test.cpp
similarity index 100%
rename from media/codecs/amrnb/dec/test/amrnbdec_test.cpp
rename to media/module/codecs/amrnb/dec/test/amrnbdec_test.cpp
diff --git a/media/codecs/amrnb/enc/Android.bp b/media/module/codecs/amrnb/enc/Android.bp
similarity index 100%
rename from media/codecs/amrnb/enc/Android.bp
rename to media/module/codecs/amrnb/enc/Android.bp
diff --git a/media/codecs/amrnb/enc/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrnb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrnb/enc/NOTICE b/media/module/codecs/amrnb/enc/NOTICE
similarity index 100%
rename from media/codecs/amrnb/enc/NOTICE
rename to media/module/codecs/amrnb/enc/NOTICE
diff --git a/media/codecs/amrnb/enc/fuzzer/Android.bp b/media/module/codecs/amrnb/enc/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrnb/enc/fuzzer/Android.bp
rename to media/module/codecs/amrnb/enc/fuzzer/Android.bp
diff --git a/media/codecs/amrnb/enc/fuzzer/README.md b/media/module/codecs/amrnb/enc/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrnb/enc/fuzzer/README.md
rename to media/module/codecs/amrnb/enc/fuzzer/README.md
diff --git a/media/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp b/media/module/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
rename to media/module/codecs/amrnb/enc/fuzzer/amrnb_enc_fuzzer.cpp
diff --git a/media/codecs/amrnb/enc/src/amrencode.cpp b/media/module/codecs/amrnb/enc/src/amrencode.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/amrencode.cpp
rename to media/module/codecs/amrnb/enc/src/amrencode.cpp
diff --git a/media/codecs/amrnb/enc/src/amrencode.h b/media/module/codecs/amrnb/enc/src/amrencode.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/amrencode.h
rename to media/module/codecs/amrnb/enc/src/amrencode.h
diff --git a/media/codecs/amrnb/enc/src/autocorr.cpp b/media/module/codecs/amrnb/enc/src/autocorr.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/autocorr.cpp
rename to media/module/codecs/amrnb/enc/src/autocorr.cpp
diff --git a/media/codecs/amrnb/enc/src/autocorr.h b/media/module/codecs/amrnb/enc/src/autocorr.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/autocorr.h
rename to media/module/codecs/amrnb/enc/src/autocorr.h
diff --git a/media/codecs/amrnb/enc/src/c1035pf.cpp b/media/module/codecs/amrnb/enc/src/c1035pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c1035pf.cpp
rename to media/module/codecs/amrnb/enc/src/c1035pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c1035pf.h b/media/module/codecs/amrnb/enc/src/c1035pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c1035pf.h
rename to media/module/codecs/amrnb/enc/src/c1035pf.h
diff --git a/media/codecs/amrnb/enc/src/c2_11pf.cpp b/media/module/codecs/amrnb/enc/src/c2_11pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_11pf.cpp
rename to media/module/codecs/amrnb/enc/src/c2_11pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c2_11pf.h b/media/module/codecs/amrnb/enc/src/c2_11pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_11pf.h
rename to media/module/codecs/amrnb/enc/src/c2_11pf.h
diff --git a/media/codecs/amrnb/enc/src/c2_9pf.cpp b/media/module/codecs/amrnb/enc/src/c2_9pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_9pf.cpp
rename to media/module/codecs/amrnb/enc/src/c2_9pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c2_9pf.h b/media/module/codecs/amrnb/enc/src/c2_9pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c2_9pf.h
rename to media/module/codecs/amrnb/enc/src/c2_9pf.h
diff --git a/media/codecs/amrnb/enc/src/c3_14pf.cpp b/media/module/codecs/amrnb/enc/src/c3_14pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c3_14pf.cpp
rename to media/module/codecs/amrnb/enc/src/c3_14pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c3_14pf.h b/media/module/codecs/amrnb/enc/src/c3_14pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c3_14pf.h
rename to media/module/codecs/amrnb/enc/src/c3_14pf.h
diff --git a/media/codecs/amrnb/enc/src/c4_17pf.cpp b/media/module/codecs/amrnb/enc/src/c4_17pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c4_17pf.cpp
rename to media/module/codecs/amrnb/enc/src/c4_17pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c4_17pf.h b/media/module/codecs/amrnb/enc/src/c4_17pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c4_17pf.h
rename to media/module/codecs/amrnb/enc/src/c4_17pf.h
diff --git a/media/codecs/amrnb/enc/src/c8_31pf.cpp b/media/module/codecs/amrnb/enc/src/c8_31pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/c8_31pf.cpp
rename to media/module/codecs/amrnb/enc/src/c8_31pf.cpp
diff --git a/media/codecs/amrnb/enc/src/c8_31pf.h b/media/module/codecs/amrnb/enc/src/c8_31pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/c8_31pf.h
rename to media/module/codecs/amrnb/enc/src/c8_31pf.h
diff --git a/media/codecs/amrnb/enc/src/calc_cor.cpp b/media/module/codecs/amrnb/enc/src/calc_cor.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_cor.cpp
rename to media/module/codecs/amrnb/enc/src/calc_cor.cpp
diff --git a/media/codecs/amrnb/enc/src/calc_cor.h b/media/module/codecs/amrnb/enc/src/calc_cor.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_cor.h
rename to media/module/codecs/amrnb/enc/src/calc_cor.h
diff --git a/media/codecs/amrnb/enc/src/calc_en.cpp b/media/module/codecs/amrnb/enc/src/calc_en.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_en.cpp
rename to media/module/codecs/amrnb/enc/src/calc_en.cpp
diff --git a/media/codecs/amrnb/enc/src/calc_en.h b/media/module/codecs/amrnb/enc/src/calc_en.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/calc_en.h
rename to media/module/codecs/amrnb/enc/src/calc_en.h
diff --git a/media/codecs/amrnb/enc/src/cbsearch.cpp b/media/module/codecs/amrnb/enc/src/cbsearch.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cbsearch.cpp
rename to media/module/codecs/amrnb/enc/src/cbsearch.cpp
diff --git a/media/codecs/amrnb/enc/src/cbsearch.h b/media/module/codecs/amrnb/enc/src/cbsearch.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cbsearch.h
rename to media/module/codecs/amrnb/enc/src/cbsearch.h
diff --git a/media/codecs/amrnb/enc/src/cl_ltp.cpp b/media/module/codecs/amrnb/enc/src/cl_ltp.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cl_ltp.cpp
rename to media/module/codecs/amrnb/enc/src/cl_ltp.cpp
diff --git a/media/codecs/amrnb/enc/src/cl_ltp.h b/media/module/codecs/amrnb/enc/src/cl_ltp.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cl_ltp.h
rename to media/module/codecs/amrnb/enc/src/cl_ltp.h
diff --git a/media/codecs/amrnb/enc/src/cod_amr.cpp b/media/module/codecs/amrnb/enc/src/cod_amr.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cod_amr.cpp
rename to media/module/codecs/amrnb/enc/src/cod_amr.cpp
diff --git a/media/codecs/amrnb/enc/src/cod_amr.h b/media/module/codecs/amrnb/enc/src/cod_amr.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cod_amr.h
rename to media/module/codecs/amrnb/enc/src/cod_amr.h
diff --git a/media/codecs/amrnb/enc/src/convolve.cpp b/media/module/codecs/amrnb/enc/src/convolve.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/convolve.cpp
rename to media/module/codecs/amrnb/enc/src/convolve.cpp
diff --git a/media/codecs/amrnb/enc/src/convolve.h b/media/module/codecs/amrnb/enc/src/convolve.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/convolve.h
rename to media/module/codecs/amrnb/enc/src/convolve.h
diff --git a/media/codecs/amrnb/enc/src/cor_h.cpp b/media/module/codecs/amrnb/enc/src/cor_h.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h.cpp
rename to media/module/codecs/amrnb/enc/src/cor_h.cpp
diff --git a/media/codecs/amrnb/enc/src/cor_h.h b/media/module/codecs/amrnb/enc/src/cor_h.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h.h
rename to media/module/codecs/amrnb/enc/src/cor_h.h
diff --git a/media/codecs/amrnb/enc/src/cor_h_x.cpp b/media/module/codecs/amrnb/enc/src/cor_h_x.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x.cpp
rename to media/module/codecs/amrnb/enc/src/cor_h_x.cpp
diff --git a/media/codecs/amrnb/enc/src/cor_h_x.h b/media/module/codecs/amrnb/enc/src/cor_h_x.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x.h
rename to media/module/codecs/amrnb/enc/src/cor_h_x.h
diff --git a/media/codecs/amrnb/enc/src/cor_h_x2.cpp b/media/module/codecs/amrnb/enc/src/cor_h_x2.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x2.cpp
rename to media/module/codecs/amrnb/enc/src/cor_h_x2.cpp
diff --git a/media/codecs/amrnb/enc/src/cor_h_x2.h b/media/module/codecs/amrnb/enc/src/cor_h_x2.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/cor_h_x2.h
rename to media/module/codecs/amrnb/enc/src/cor_h_x2.h
diff --git a/media/codecs/amrnb/enc/src/corrwght_tab.cpp b/media/module/codecs/amrnb/enc/src/corrwght_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/corrwght_tab.cpp
rename to media/module/codecs/amrnb/enc/src/corrwght_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/dtx_enc.cpp b/media/module/codecs/amrnb/enc/src/dtx_enc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/dtx_enc.cpp
rename to media/module/codecs/amrnb/enc/src/dtx_enc.cpp
diff --git a/media/codecs/amrnb/enc/src/dtx_enc.h b/media/module/codecs/amrnb/enc/src/dtx_enc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/dtx_enc.h
rename to media/module/codecs/amrnb/enc/src/dtx_enc.h
diff --git a/media/codecs/amrnb/enc/src/enc_lag3.cpp b/media/module/codecs/amrnb/enc/src/enc_lag3.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag3.cpp
rename to media/module/codecs/amrnb/enc/src/enc_lag3.cpp
diff --git a/media/codecs/amrnb/enc/src/enc_lag3.h b/media/module/codecs/amrnb/enc/src/enc_lag3.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag3.h
rename to media/module/codecs/amrnb/enc/src/enc_lag3.h
diff --git a/media/codecs/amrnb/enc/src/enc_lag6.cpp b/media/module/codecs/amrnb/enc/src/enc_lag6.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag6.cpp
rename to media/module/codecs/amrnb/enc/src/enc_lag6.cpp
diff --git a/media/codecs/amrnb/enc/src/enc_lag6.h b/media/module/codecs/amrnb/enc/src/enc_lag6.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_lag6.h
rename to media/module/codecs/amrnb/enc/src/enc_lag6.h
diff --git a/media/codecs/amrnb/enc/src/enc_output_format_tab.cpp b/media/module/codecs/amrnb/enc/src/enc_output_format_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/enc_output_format_tab.cpp
rename to media/module/codecs/amrnb/enc/src/enc_output_format_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/ets_to_if2.cpp b/media/module/codecs/amrnb/enc/src/ets_to_if2.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_if2.cpp
rename to media/module/codecs/amrnb/enc/src/ets_to_if2.cpp
diff --git a/media/codecs/amrnb/enc/src/ets_to_if2.h b/media/module/codecs/amrnb/enc/src/ets_to_if2.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_if2.h
rename to media/module/codecs/amrnb/enc/src/ets_to_if2.h
diff --git a/media/codecs/amrnb/enc/src/ets_to_wmf.cpp b/media/module/codecs/amrnb/enc/src/ets_to_wmf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_wmf.cpp
rename to media/module/codecs/amrnb/enc/src/ets_to_wmf.cpp
diff --git a/media/codecs/amrnb/enc/src/ets_to_wmf.h b/media/module/codecs/amrnb/enc/src/ets_to_wmf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ets_to_wmf.h
rename to media/module/codecs/amrnb/enc/src/ets_to_wmf.h
diff --git a/media/codecs/amrnb/enc/src/g_adapt.cpp b/media/module/codecs/amrnb/enc/src/g_adapt.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_adapt.cpp
rename to media/module/codecs/amrnb/enc/src/g_adapt.cpp
diff --git a/media/codecs/amrnb/enc/src/g_adapt.h b/media/module/codecs/amrnb/enc/src/g_adapt.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_adapt.h
rename to media/module/codecs/amrnb/enc/src/g_adapt.h
diff --git a/media/codecs/amrnb/enc/src/g_code.cpp b/media/module/codecs/amrnb/enc/src/g_code.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_code.cpp
rename to media/module/codecs/amrnb/enc/src/g_code.cpp
diff --git a/media/codecs/amrnb/enc/src/g_code.h b/media/module/codecs/amrnb/enc/src/g_code.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_code.h
rename to media/module/codecs/amrnb/enc/src/g_code.h
diff --git a/media/codecs/amrnb/enc/src/g_pitch.cpp b/media/module/codecs/amrnb/enc/src/g_pitch.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_pitch.cpp
rename to media/module/codecs/amrnb/enc/src/g_pitch.cpp
diff --git a/media/codecs/amrnb/enc/src/g_pitch.h b/media/module/codecs/amrnb/enc/src/g_pitch.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/g_pitch.h
rename to media/module/codecs/amrnb/enc/src/g_pitch.h
diff --git a/media/codecs/amrnb/enc/src/gain_q.cpp b/media/module/codecs/amrnb/enc/src/gain_q.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/gain_q.cpp
rename to media/module/codecs/amrnb/enc/src/gain_q.cpp
diff --git a/media/codecs/amrnb/enc/src/gain_q.h b/media/module/codecs/amrnb/enc/src/gain_q.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/gain_q.h
rename to media/module/codecs/amrnb/enc/src/gain_q.h
diff --git a/media/codecs/amrnb/enc/src/gsmamr_enc.h b/media/module/codecs/amrnb/enc/src/gsmamr_enc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/gsmamr_enc.h
rename to media/module/codecs/amrnb/enc/src/gsmamr_enc.h
diff --git a/media/codecs/amrnb/enc/src/hp_max.cpp b/media/module/codecs/amrnb/enc/src/hp_max.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/hp_max.cpp
rename to media/module/codecs/amrnb/enc/src/hp_max.cpp
diff --git a/media/codecs/amrnb/enc/src/hp_max.h b/media/module/codecs/amrnb/enc/src/hp_max.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/hp_max.h
rename to media/module/codecs/amrnb/enc/src/hp_max.h
diff --git a/media/codecs/amrnb/enc/src/inter_36.cpp b/media/module/codecs/amrnb/enc/src/inter_36.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36.cpp
rename to media/module/codecs/amrnb/enc/src/inter_36.cpp
diff --git a/media/codecs/amrnb/enc/src/inter_36.h b/media/module/codecs/amrnb/enc/src/inter_36.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36.h
rename to media/module/codecs/amrnb/enc/src/inter_36.h
diff --git a/media/codecs/amrnb/enc/src/inter_36_tab.cpp b/media/module/codecs/amrnb/enc/src/inter_36_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36_tab.cpp
rename to media/module/codecs/amrnb/enc/src/inter_36_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/inter_36_tab.h b/media/module/codecs/amrnb/enc/src/inter_36_tab.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/inter_36_tab.h
rename to media/module/codecs/amrnb/enc/src/inter_36_tab.h
diff --git a/media/codecs/amrnb/enc/src/l_comp.cpp b/media/module/codecs/amrnb/enc/src/l_comp.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/l_comp.cpp
rename to media/module/codecs/amrnb/enc/src/l_comp.cpp
diff --git a/media/codecs/amrnb/enc/src/l_extract.cpp b/media/module/codecs/amrnb/enc/src/l_extract.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/l_extract.cpp
rename to media/module/codecs/amrnb/enc/src/l_extract.cpp
diff --git a/media/codecs/amrnb/enc/src/l_negate.cpp b/media/module/codecs/amrnb/enc/src/l_negate.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/l_negate.cpp
rename to media/module/codecs/amrnb/enc/src/l_negate.cpp
diff --git a/media/codecs/amrnb/enc/src/lag_wind.cpp b/media/module/codecs/amrnb/enc/src/lag_wind.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind.cpp
rename to media/module/codecs/amrnb/enc/src/lag_wind.cpp
diff --git a/media/codecs/amrnb/enc/src/lag_wind.h b/media/module/codecs/amrnb/enc/src/lag_wind.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind.h
rename to media/module/codecs/amrnb/enc/src/lag_wind.h
diff --git a/media/codecs/amrnb/enc/src/lag_wind_tab.cpp b/media/module/codecs/amrnb/enc/src/lag_wind_tab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind_tab.cpp
rename to media/module/codecs/amrnb/enc/src/lag_wind_tab.cpp
diff --git a/media/codecs/amrnb/enc/src/lag_wind_tab.h b/media/module/codecs/amrnb/enc/src/lag_wind_tab.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/lag_wind_tab.h
rename to media/module/codecs/amrnb/enc/src/lag_wind_tab.h
diff --git a/media/codecs/amrnb/enc/src/levinson.cpp b/media/module/codecs/amrnb/enc/src/levinson.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/levinson.cpp
rename to media/module/codecs/amrnb/enc/src/levinson.cpp
diff --git a/media/codecs/amrnb/enc/src/levinson.h b/media/module/codecs/amrnb/enc/src/levinson.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/levinson.h
rename to media/module/codecs/amrnb/enc/src/levinson.h
diff --git a/media/codecs/amrnb/enc/src/lpc.cpp b/media/module/codecs/amrnb/enc/src/lpc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/lpc.cpp
rename to media/module/codecs/amrnb/enc/src/lpc.cpp
diff --git a/media/codecs/amrnb/enc/src/lpc.h b/media/module/codecs/amrnb/enc/src/lpc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/lpc.h
rename to media/module/codecs/amrnb/enc/src/lpc.h
diff --git a/media/codecs/amrnb/enc/src/ol_ltp.cpp b/media/module/codecs/amrnb/enc/src/ol_ltp.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ol_ltp.cpp
rename to media/module/codecs/amrnb/enc/src/ol_ltp.cpp
diff --git a/media/codecs/amrnb/enc/src/ol_ltp.h b/media/module/codecs/amrnb/enc/src/ol_ltp.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ol_ltp.h
rename to media/module/codecs/amrnb/enc/src/ol_ltp.h
diff --git a/media/codecs/amrnb/enc/src/p_ol_wgh.cpp b/media/module/codecs/amrnb/enc/src/p_ol_wgh.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/p_ol_wgh.cpp
rename to media/module/codecs/amrnb/enc/src/p_ol_wgh.cpp
diff --git a/media/codecs/amrnb/enc/src/pitch_fr.cpp b/media/module/codecs/amrnb/enc/src/pitch_fr.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_fr.cpp
rename to media/module/codecs/amrnb/enc/src/pitch_fr.cpp
diff --git a/media/codecs/amrnb/enc/src/pitch_fr.h b/media/module/codecs/amrnb/enc/src/pitch_fr.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_fr.h
rename to media/module/codecs/amrnb/enc/src/pitch_fr.h
diff --git a/media/codecs/amrnb/enc/src/pitch_ol.cpp b/media/module/codecs/amrnb/enc/src/pitch_ol.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_ol.cpp
rename to media/module/codecs/amrnb/enc/src/pitch_ol.cpp
diff --git a/media/codecs/amrnb/enc/src/pitch_ol.h b/media/module/codecs/amrnb/enc/src/pitch_ol.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pitch_ol.h
rename to media/module/codecs/amrnb/enc/src/pitch_ol.h
diff --git a/media/codecs/amrnb/enc/src/pre_big.cpp b/media/module/codecs/amrnb/enc/src/pre_big.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_big.cpp
rename to media/module/codecs/amrnb/enc/src/pre_big.cpp
diff --git a/media/codecs/amrnb/enc/src/pre_big.h b/media/module/codecs/amrnb/enc/src/pre_big.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_big.h
rename to media/module/codecs/amrnb/enc/src/pre_big.h
diff --git a/media/codecs/amrnb/enc/src/pre_proc.cpp b/media/module/codecs/amrnb/enc/src/pre_proc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_proc.cpp
rename to media/module/codecs/amrnb/enc/src/pre_proc.cpp
diff --git a/media/codecs/amrnb/enc/src/pre_proc.h b/media/module/codecs/amrnb/enc/src/pre_proc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/pre_proc.h
rename to media/module/codecs/amrnb/enc/src/pre_proc.h
diff --git a/media/codecs/amrnb/enc/src/prm2bits.cpp b/media/module/codecs/amrnb/enc/src/prm2bits.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/prm2bits.cpp
rename to media/module/codecs/amrnb/enc/src/prm2bits.cpp
diff --git a/media/codecs/amrnb/enc/src/prm2bits.h b/media/module/codecs/amrnb/enc/src/prm2bits.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/prm2bits.h
rename to media/module/codecs/amrnb/enc/src/prm2bits.h
diff --git a/media/codecs/amrnb/enc/src/q_gain_c.cpp b/media/module/codecs/amrnb/enc/src/q_gain_c.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_c.cpp
rename to media/module/codecs/amrnb/enc/src/q_gain_c.cpp
diff --git a/media/codecs/amrnb/enc/src/q_gain_c.h b/media/module/codecs/amrnb/enc/src/q_gain_c.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_c.h
rename to media/module/codecs/amrnb/enc/src/q_gain_c.h
diff --git a/media/codecs/amrnb/enc/src/q_gain_p.cpp b/media/module/codecs/amrnb/enc/src/q_gain_p.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_p.cpp
rename to media/module/codecs/amrnb/enc/src/q_gain_p.cpp
diff --git a/media/codecs/amrnb/enc/src/q_gain_p.h b/media/module/codecs/amrnb/enc/src/q_gain_p.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/q_gain_p.h
rename to media/module/codecs/amrnb/enc/src/q_gain_p.h
diff --git a/media/codecs/amrnb/enc/src/qgain475.cpp b/media/module/codecs/amrnb/enc/src/qgain475.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain475.cpp
rename to media/module/codecs/amrnb/enc/src/qgain475.cpp
diff --git a/media/codecs/amrnb/enc/src/qgain475.h b/media/module/codecs/amrnb/enc/src/qgain475.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain475.h
rename to media/module/codecs/amrnb/enc/src/qgain475.h
diff --git a/media/codecs/amrnb/enc/src/qgain795.cpp b/media/module/codecs/amrnb/enc/src/qgain795.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain795.cpp
rename to media/module/codecs/amrnb/enc/src/qgain795.cpp
diff --git a/media/codecs/amrnb/enc/src/qgain795.h b/media/module/codecs/amrnb/enc/src/qgain795.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/qgain795.h
rename to media/module/codecs/amrnb/enc/src/qgain795.h
diff --git a/media/codecs/amrnb/enc/src/qua_gain.cpp b/media/module/codecs/amrnb/enc/src/qua_gain.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/qua_gain.cpp
rename to media/module/codecs/amrnb/enc/src/qua_gain.cpp
diff --git a/media/codecs/amrnb/enc/src/s10_8pf.cpp b/media/module/codecs/amrnb/enc/src/s10_8pf.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/s10_8pf.cpp
rename to media/module/codecs/amrnb/enc/src/s10_8pf.cpp
diff --git a/media/codecs/amrnb/enc/src/s10_8pf.h b/media/module/codecs/amrnb/enc/src/s10_8pf.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/s10_8pf.h
rename to media/module/codecs/amrnb/enc/src/s10_8pf.h
diff --git a/media/codecs/amrnb/enc/src/set_sign.cpp b/media/module/codecs/amrnb/enc/src/set_sign.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/set_sign.cpp
rename to media/module/codecs/amrnb/enc/src/set_sign.cpp
diff --git a/media/codecs/amrnb/enc/src/set_sign.h b/media/module/codecs/amrnb/enc/src/set_sign.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/set_sign.h
rename to media/module/codecs/amrnb/enc/src/set_sign.h
diff --git a/media/codecs/amrnb/enc/src/sid_sync.cpp b/media/module/codecs/amrnb/enc/src/sid_sync.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/sid_sync.cpp
rename to media/module/codecs/amrnb/enc/src/sid_sync.cpp
diff --git a/media/codecs/amrnb/enc/src/sid_sync.h b/media/module/codecs/amrnb/enc/src/sid_sync.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/sid_sync.h
rename to media/module/codecs/amrnb/enc/src/sid_sync.h
diff --git a/media/codecs/amrnb/enc/src/sp_enc.cpp b/media/module/codecs/amrnb/enc/src/sp_enc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/sp_enc.cpp
rename to media/module/codecs/amrnb/enc/src/sp_enc.cpp
diff --git a/media/codecs/amrnb/enc/src/sp_enc.h b/media/module/codecs/amrnb/enc/src/sp_enc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/sp_enc.h
rename to media/module/codecs/amrnb/enc/src/sp_enc.h
diff --git a/media/codecs/amrnb/enc/src/spreproc.cpp b/media/module/codecs/amrnb/enc/src/spreproc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/spreproc.cpp
rename to media/module/codecs/amrnb/enc/src/spreproc.cpp
diff --git a/media/codecs/amrnb/enc/src/spreproc.h b/media/module/codecs/amrnb/enc/src/spreproc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/spreproc.h
rename to media/module/codecs/amrnb/enc/src/spreproc.h
diff --git a/media/codecs/amrnb/enc/src/spstproc.cpp b/media/module/codecs/amrnb/enc/src/spstproc.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/spstproc.cpp
rename to media/module/codecs/amrnb/enc/src/spstproc.cpp
diff --git a/media/codecs/amrnb/enc/src/spstproc.h b/media/module/codecs/amrnb/enc/src/spstproc.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/spstproc.h
rename to media/module/codecs/amrnb/enc/src/spstproc.h
diff --git a/media/codecs/amrnb/enc/src/ton_stab.cpp b/media/module/codecs/amrnb/enc/src/ton_stab.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/src/ton_stab.cpp
rename to media/module/codecs/amrnb/enc/src/ton_stab.cpp
diff --git a/media/codecs/amrnb/enc/src/ton_stab.h b/media/module/codecs/amrnb/enc/src/ton_stab.h
similarity index 100%
rename from media/codecs/amrnb/enc/src/ton_stab.h
rename to media/module/codecs/amrnb/enc/src/ton_stab.h
diff --git a/media/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h b/media/module/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
similarity index 100%
rename from media/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
rename to media/module/codecs/amrnb/enc/test/AmrnbEncTestEnvironment.h
diff --git a/media/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp b/media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
rename to media/module/codecs/amrnb/enc/test/AmrnbEncoderTest.cpp
diff --git a/media/codecs/amrnb/enc/test/Android.bp b/media/module/codecs/amrnb/enc/test/Android.bp
similarity index 90%
rename from media/codecs/amrnb/enc/test/Android.bp
rename to media/module/codecs/amrnb/enc/test/Android.bp
index 7e393e3..5871486 100644
--- a/media/codecs/amrnb/enc/test/Android.bp
+++ b/media/module/codecs/amrnb/enc/test/Android.bp
@@ -58,4 +58,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrnb/enc/test/AmrnbEncoderTest.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/amrnb/enc/test/AndroidTest.xml b/media/module/codecs/amrnb/enc/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrnb/enc/test/AndroidTest.xml
rename to media/module/codecs/amrnb/enc/test/AndroidTest.xml
diff --git a/media/codecs/amrnb/enc/test/README.md b/media/module/codecs/amrnb/enc/test/README.md
similarity index 100%
rename from media/codecs/amrnb/enc/test/README.md
rename to media/module/codecs/amrnb/enc/test/README.md
diff --git a/media/codecs/amrnb/enc/test/amrnb_enc_test.cpp b/media/module/codecs/amrnb/enc/test/amrnb_enc_test.cpp
similarity index 100%
rename from media/codecs/amrnb/enc/test/amrnb_enc_test.cpp
rename to media/module/codecs/amrnb/enc/test/amrnb_enc_test.cpp
diff --git a/media/codecs/amrnb/fuzzer/Android.bp b/media/module/codecs/amrnb/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrnb/fuzzer/Android.bp
rename to media/module/codecs/amrnb/fuzzer/Android.bp
diff --git a/media/codecs/amrnb/fuzzer/README.md b/media/module/codecs/amrnb/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrnb/fuzzer/README.md
rename to media/module/codecs/amrnb/fuzzer/README.md
diff --git a/media/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp b/media/module/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
rename to media/module/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
diff --git a/media/codecs/amrnb/patent_disclaimer.txt b/media/module/codecs/amrnb/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/amrnb/patent_disclaimer.txt
rename to media/module/codecs/amrnb/patent_disclaimer.txt
diff --git a/media/codecs/amrwb/dec/Android.bp b/media/module/codecs/amrwb/dec/Android.bp
similarity index 100%
rename from media/codecs/amrwb/dec/Android.bp
rename to media/module/codecs/amrwb/dec/Android.bp
diff --git a/media/codecs/amrwb/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrwb/dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrwb/dec/NOTICE b/media/module/codecs/amrwb/dec/NOTICE
similarity index 100%
rename from media/codecs/amrwb/dec/NOTICE
rename to media/module/codecs/amrwb/dec/NOTICE
diff --git a/media/codecs/amrwb/dec/TEST_MAPPING b/media/module/codecs/amrwb/dec/TEST_MAPPING
similarity index 100%
rename from media/codecs/amrwb/dec/TEST_MAPPING
rename to media/module/codecs/amrwb/dec/TEST_MAPPING
diff --git a/media/codecs/amrwb/dec/fuzzer/Android.bp b/media/module/codecs/amrwb/dec/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrwb/dec/fuzzer/Android.bp
rename to media/module/codecs/amrwb/dec/fuzzer/Android.bp
diff --git a/media/codecs/amrwb/dec/fuzzer/README.md b/media/module/codecs/amrwb/dec/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrwb/dec/fuzzer/README.md
rename to media/module/codecs/amrwb/dec/fuzzer/README.md
diff --git a/media/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp b/media/module/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
rename to media/module/codecs/amrwb/dec/fuzzer/amrwb_dec_fuzzer.cpp
diff --git a/media/codecs/amrwb/dec/include/pvamrwbdecoder_api.h b/media/module/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
similarity index 100%
rename from media/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
rename to media/module/codecs/amrwb/dec/include/pvamrwbdecoder_api.h
diff --git a/media/codecs/amrwb/dec/patent_disclaimer.txt b/media/module/codecs/amrwb/dec/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/amrwb/dec/patent_disclaimer.txt
rename to media/module/codecs/amrwb/dec/patent_disclaimer.txt
diff --git a/media/codecs/amrwb/dec/src/agc2_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/agc2_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/agc2_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/agc2_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/band_pass_6k_7k.cpp b/media/module/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
rename to media/module/codecs/amrwb/dec/src/band_pass_6k_7k.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp b/media/module/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
rename to media/module/codecs/amrwb/dec/src/dec_acelp_2p_in_64.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp b/media/module/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
rename to media/module/codecs/amrwb/dec/src/dec_acelp_4p_in_64.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_alg_codebook.cpp b/media/module/codecs/amrwb/dec/src/dec_alg_codebook.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_alg_codebook.cpp
rename to media/module/codecs/amrwb/dec/src/dec_alg_codebook.cpp
diff --git a/media/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/dec_gain2_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/deemphasis_32.cpp b/media/module/codecs/amrwb/dec/src/deemphasis_32.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/deemphasis_32.cpp
rename to media/module/codecs/amrwb/dec/src/deemphasis_32.cpp
diff --git a/media/codecs/amrwb/dec/src/dtx.h b/media/module/codecs/amrwb/dec/src/dtx.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/dtx.h
rename to media/module/codecs/amrwb/dec/src/dtx.h
diff --git a/media/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/dtx_decoder_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/e_pv_amrwbdec.h b/media/module/codecs/amrwb/dec/src/e_pv_amrwbdec.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/e_pv_amrwbdec.h
rename to media/module/codecs/amrwb/dec/src/e_pv_amrwbdec.h
diff --git a/media/codecs/amrwb/dec/src/get_amr_wb_bits.cpp b/media/module/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
rename to media/module/codecs/amrwb/dec/src/get_amr_wb_bits.cpp
diff --git a/media/codecs/amrwb/dec/src/get_amr_wb_bits.h b/media/module/codecs/amrwb/dec/src/get_amr_wb_bits.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/get_amr_wb_bits.h
rename to media/module/codecs/amrwb/dec/src/get_amr_wb_bits.h
diff --git a/media/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp b/media/module/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
rename to media/module/codecs/amrwb/dec/src/highpass_400hz_at_12k8.cpp
diff --git a/media/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp b/media/module/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
rename to media/module/codecs/amrwb/dec/src/highpass_50hz_at_12k8.cpp
diff --git a/media/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp b/media/module/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
rename to media/module/codecs/amrwb/dec/src/homing_amr_wb_dec.cpp
diff --git a/media/codecs/amrwb/dec/src/interpolate_isp.cpp b/media/module/codecs/amrwb/dec/src/interpolate_isp.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/interpolate_isp.cpp
rename to media/module/codecs/amrwb/dec/src/interpolate_isp.cpp
diff --git a/media/codecs/amrwb/dec/src/isf_extrapolation.cpp b/media/module/codecs/amrwb/dec/src/isf_extrapolation.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/isf_extrapolation.cpp
rename to media/module/codecs/amrwb/dec/src/isf_extrapolation.cpp
diff --git a/media/codecs/amrwb/dec/src/isp_az.cpp b/media/module/codecs/amrwb/dec/src/isp_az.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/isp_az.cpp
rename to media/module/codecs/amrwb/dec/src/isp_az.cpp
diff --git a/media/codecs/amrwb/dec/src/isp_isf.cpp b/media/module/codecs/amrwb/dec/src/isp_isf.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/isp_isf.cpp
rename to media/module/codecs/amrwb/dec/src/isp_isf.cpp
diff --git a/media/codecs/amrwb/dec/src/lagconceal.cpp b/media/module/codecs/amrwb/dec/src/lagconceal.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/lagconceal.cpp
rename to media/module/codecs/amrwb/dec/src/lagconceal.cpp
diff --git a/media/codecs/amrwb/dec/src/low_pass_filt_7k.cpp b/media/module/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
rename to media/module/codecs/amrwb/dec/src/low_pass_filt_7k.cpp
diff --git a/media/codecs/amrwb/dec/src/median5.cpp b/media/module/codecs/amrwb/dec/src/median5.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/median5.cpp
rename to media/module/codecs/amrwb/dec/src/median5.cpp
diff --git a/media/codecs/amrwb/dec/src/mime_io.cpp b/media/module/codecs/amrwb/dec/src/mime_io.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/mime_io.cpp
rename to media/module/codecs/amrwb/dec/src/mime_io.cpp
diff --git a/media/codecs/amrwb/dec/src/mime_io.h b/media/module/codecs/amrwb/dec/src/mime_io.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/mime_io.h
rename to media/module/codecs/amrwb/dec/src/mime_io.h
diff --git a/media/codecs/amrwb/dec/src/noise_gen_amrwb.cpp b/media/module/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
rename to media/module/codecs/amrwb/dec/src/noise_gen_amrwb.cpp
diff --git a/media/codecs/amrwb/dec/src/normalize_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/normalize_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/normalize_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/normalize_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/normalize_amr_wb.h b/media/module/codecs/amrwb/dec/src/normalize_amr_wb.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/normalize_amr_wb.h
rename to media/module/codecs/amrwb/dec/src/normalize_amr_wb.h
diff --git a/media/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp b/media/module/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
rename to media/module/codecs/amrwb/dec/src/oversamp_12k8_to_16k.cpp
diff --git a/media/codecs/amrwb/dec/src/phase_dispersion.cpp b/media/module/codecs/amrwb/dec/src/phase_dispersion.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/phase_dispersion.cpp
rename to media/module/codecs/amrwb/dec/src/phase_dispersion.cpp
diff --git a/media/codecs/amrwb/dec/src/pit_shrp.cpp b/media/module/codecs/amrwb/dec/src/pit_shrp.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pit_shrp.cpp
rename to media/module/codecs/amrwb/dec/src/pit_shrp.cpp
diff --git a/media/codecs/amrwb/dec/src/pred_lt4.cpp b/media/module/codecs/amrwb/dec/src/pred_lt4.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pred_lt4.cpp
rename to media/module/codecs/amrwb/dec/src/pred_lt4.cpp
diff --git a/media/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp b/media/module/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
rename to media/module/codecs/amrwb/dec/src/preemph_amrwb_dec.cpp
diff --git a/media/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h b/media/module/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
rename to media/module/codecs/amrwb/dec/src/pv_amr_wb_type_defs.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwb_math_op.cpp b/media/module/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
rename to media/module/codecs/amrwb/dec/src/pvamrwb_math_op.cpp
diff --git a/media/codecs/amrwb/dec/src/pvamrwb_math_op.h b/media/module/codecs/amrwb/dec/src/pvamrwb_math_op.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwb_math_op.h
rename to media/module/codecs/amrwb/dec/src/pvamrwb_math_op.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder.cpp b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder.cpp
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_acelp.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_armv5.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_cequivalent.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_basic_op_gcc_armv5.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_cnst.h
diff --git a/media/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h b/media/module/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
rename to media/module/codecs/amrwb/dec/src/pvamrwbdecoder_mem_funcs.h
diff --git a/media/codecs/amrwb/dec/src/q_gain2_tab.cpp b/media/module/codecs/amrwb/dec/src/q_gain2_tab.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/q_gain2_tab.cpp
rename to media/module/codecs/amrwb/dec/src/q_gain2_tab.cpp
diff --git a/media/codecs/amrwb/dec/src/q_pulse.h b/media/module/codecs/amrwb/dec/src/q_pulse.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/q_pulse.h
rename to media/module/codecs/amrwb/dec/src/q_pulse.h
diff --git a/media/codecs/amrwb/dec/src/qisf_ns.cpp b/media/module/codecs/amrwb/dec/src/qisf_ns.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qisf_ns.cpp
rename to media/module/codecs/amrwb/dec/src/qisf_ns.cpp
diff --git a/media/codecs/amrwb/dec/src/qisf_ns.h b/media/module/codecs/amrwb/dec/src/qisf_ns.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/qisf_ns.h
rename to media/module/codecs/amrwb/dec/src/qisf_ns.h
diff --git a/media/codecs/amrwb/dec/src/qisf_ns_tab.cpp b/media/module/codecs/amrwb/dec/src/qisf_ns_tab.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qisf_ns_tab.cpp
rename to media/module/codecs/amrwb/dec/src/qisf_ns_tab.cpp
diff --git a/media/codecs/amrwb/dec/src/qpisf_2s.cpp b/media/module/codecs/amrwb/dec/src/qpisf_2s.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qpisf_2s.cpp
rename to media/module/codecs/amrwb/dec/src/qpisf_2s.cpp
diff --git a/media/codecs/amrwb/dec/src/qpisf_2s.h b/media/module/codecs/amrwb/dec/src/qpisf_2s.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/qpisf_2s.h
rename to media/module/codecs/amrwb/dec/src/qpisf_2s.h
diff --git a/media/codecs/amrwb/dec/src/qpisf_2s_tab.cpp b/media/module/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
rename to media/module/codecs/amrwb/dec/src/qpisf_2s_tab.cpp
diff --git a/media/codecs/amrwb/dec/src/scale_signal.cpp b/media/module/codecs/amrwb/dec/src/scale_signal.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/scale_signal.cpp
rename to media/module/codecs/amrwb/dec/src/scale_signal.cpp
diff --git a/media/codecs/amrwb/dec/src/synthesis_amr_wb.cpp b/media/module/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
rename to media/module/codecs/amrwb/dec/src/synthesis_amr_wb.cpp
diff --git a/media/codecs/amrwb/dec/src/synthesis_amr_wb.h b/media/module/codecs/amrwb/dec/src/synthesis_amr_wb.h
similarity index 100%
rename from media/codecs/amrwb/dec/src/synthesis_amr_wb.h
rename to media/module/codecs/amrwb/dec/src/synthesis_amr_wb.h
diff --git a/media/codecs/amrwb/dec/src/voice_factor.cpp b/media/module/codecs/amrwb/dec/src/voice_factor.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/voice_factor.cpp
rename to media/module/codecs/amrwb/dec/src/voice_factor.cpp
diff --git a/media/codecs/amrwb/dec/src/wb_syn_filt.cpp b/media/module/codecs/amrwb/dec/src/wb_syn_filt.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/wb_syn_filt.cpp
rename to media/module/codecs/amrwb/dec/src/wb_syn_filt.cpp
diff --git a/media/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp b/media/module/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
rename to media/module/codecs/amrwb/dec/src/weight_amrwb_lpc.cpp
diff --git a/media/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h b/media/module/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
similarity index 100%
rename from media/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
rename to media/module/codecs/amrwb/dec/test/AmrwbDecTestEnvironment.h
diff --git a/media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
similarity index 89%
rename from media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
rename to media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
index 7221b92..2cc88ce 100644
--- a/media/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
+++ b/media/module/codecs/amrwb/dec/test/AmrwbDecoderTest.cpp
@@ -21,6 +21,7 @@
 #include <utils/Log.h>
 
 #include <audio_utils/sndfile.h>
+#include <memory>
 #include <stdio.h>
 
 #include "pvamrwbdecoder.h"
@@ -121,7 +122,7 @@
 
 TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
-    void *decoderBuf = malloc(memRequirements);
+    std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
@@ -129,25 +130,21 @@
     void *amrHandle = nullptr;
     int16_t *decoderCookie;
     for (int count = 0; count < kMaxCount; count++) {
-        pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+        pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
         ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
         ALOGV("Decoder created successfully");
     }
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(AmrwbDecoderTest, DecodeTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
-    void *decoderBuf = malloc(memRequirements);
+    std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
     void *amrHandle = nullptr;
     int16_t *decoderCookie;
-    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
 
     string inputFile = gEnv->getRes() + GetParam();
@@ -159,25 +156,21 @@
     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
-    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
-    void *decoderBuf = malloc(memRequirements);
+    std::unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
     void *amrHandle = nullptr;
     int16_t *decoderCookie;
-    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
+    pvDecoder_AmrWb_Init(&amrHandle, decoderBuf.get(), &decoderCookie);
     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
 
     string inputFile = gEnv->getRes() + GetParam();
@@ -190,20 +183,18 @@
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
     // Decode 150 frames first
-    int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
+    int32_t decoderErr =
+            DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle, kNumFrameReset);
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     // Reset Decoder
-    pvDecoder_AmrWb_Reset(decoderBuf, 1);
+    pvDecoder_AmrWb_Reset(decoderBuf.get(), 1);
 
     // Start decoding again
-    decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
+    decoderErr = DecodeFrames(decoderCookie, decoderBuf.get(), outFileHandle);
     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
 
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-    }
 }
 
 INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
diff --git a/media/codecs/amrwb/dec/test/Android.bp b/media/module/codecs/amrwb/dec/test/Android.bp
similarity index 90%
rename from media/codecs/amrwb/dec/test/Android.bp
rename to media/module/codecs/amrwb/dec/test/Android.bp
index 7d0c964..7ea39ef 100644
--- a/media/codecs/amrwb/dec/test/Android.bp
+++ b/media/module/codecs/amrwb/dec/test/Android.bp
@@ -57,4 +57,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwb/test/AmrwbDecoderTest.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/amrwb/dec/test/AndroidTest.xml b/media/module/codecs/amrwb/dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrwb/dec/test/AndroidTest.xml
rename to media/module/codecs/amrwb/dec/test/AndroidTest.xml
diff --git a/media/codecs/amrwb/dec/test/README.md b/media/module/codecs/amrwb/dec/test/README.md
similarity index 100%
rename from media/codecs/amrwb/dec/test/README.md
rename to media/module/codecs/amrwb/dec/test/README.md
diff --git a/media/codecs/amrwb/dec/test/amrwbdec_test.cpp b/media/module/codecs/amrwb/dec/test/amrwbdec_test.cpp
similarity index 100%
rename from media/codecs/amrwb/dec/test/amrwbdec_test.cpp
rename to media/module/codecs/amrwb/dec/test/amrwbdec_test.cpp
diff --git a/media/codecs/amrwb/enc/Android.bp b/media/module/codecs/amrwb/enc/Android.bp
similarity index 100%
rename from media/codecs/amrwb/enc/Android.bp
rename to media/module/codecs/amrwb/enc/Android.bp
diff --git a/media/codecs/amrwb/enc/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrwb/enc/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrwb/enc/NOTICE b/media/module/codecs/amrwb/enc/NOTICE
similarity index 100%
rename from media/codecs/amrwb/enc/NOTICE
rename to media/module/codecs/amrwb/enc/NOTICE
diff --git a/media/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c b/media/module/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
rename to media/module/codecs/amrwb/enc/SampleCode/AMRWB_E_SAMPLE.c
diff --git a/media/codecs/amrwb/enc/SampleCode/Android.bp b/media/module/codecs/amrwb/enc/SampleCode/Android.bp
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/Android.bp
rename to media/module/codecs/amrwb/enc/SampleCode/Android.bp
diff --git a/media/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2 b/media/module/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
rename to media/module/codecs/amrwb/enc/SampleCode/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/amrwb/enc/SampleCode/NOTICE b/media/module/codecs/amrwb/enc/SampleCode/NOTICE
similarity index 100%
rename from media/codecs/amrwb/enc/SampleCode/NOTICE
rename to media/module/codecs/amrwb/enc/SampleCode/NOTICE
diff --git a/media/codecs/amrwb/enc/TEST_MAPPING b/media/module/codecs/amrwb/enc/TEST_MAPPING
similarity index 100%
rename from media/codecs/amrwb/enc/TEST_MAPPING
rename to media/module/codecs/amrwb/enc/TEST_MAPPING
diff --git a/media/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf b/media/module/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
similarity index 100%
rename from media/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
rename to media/module/codecs/amrwb/enc/doc/voAMRWBEncoderSDK.pdf
Binary files differ
diff --git a/media/codecs/amrwb/enc/fuzzer/Android.bp b/media/module/codecs/amrwb/enc/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/amrwb/enc/fuzzer/Android.bp
rename to media/module/codecs/amrwb/enc/fuzzer/Android.bp
diff --git a/media/codecs/amrwb/enc/fuzzer/README.md b/media/module/codecs/amrwb/enc/fuzzer/README.md
similarity index 100%
rename from media/codecs/amrwb/enc/fuzzer/README.md
rename to media/module/codecs/amrwb/enc/fuzzer/README.md
diff --git a/media/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp b/media/module/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
similarity index 100%
rename from media/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
rename to media/module/codecs/amrwb/enc/fuzzer/amrwb_enc_fuzzer.cpp
diff --git a/media/codecs/amrwb/enc/inc/acelp.h b/media/module/codecs/amrwb/enc/inc/acelp.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/acelp.h
rename to media/module/codecs/amrwb/enc/inc/acelp.h
diff --git a/media/codecs/amrwb/enc/inc/basic_op.h b/media/module/codecs/amrwb/enc/inc/basic_op.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/basic_op.h
rename to media/module/codecs/amrwb/enc/inc/basic_op.h
diff --git a/media/codecs/amrwb/enc/inc/bits.h b/media/module/codecs/amrwb/enc/inc/bits.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/bits.h
rename to media/module/codecs/amrwb/enc/inc/bits.h
diff --git a/media/codecs/amrwb/enc/inc/cnst.h b/media/module/codecs/amrwb/enc/inc/cnst.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/cnst.h
rename to media/module/codecs/amrwb/enc/inc/cnst.h
diff --git a/media/codecs/amrwb/enc/inc/cod_main.h b/media/module/codecs/amrwb/enc/inc/cod_main.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/cod_main.h
rename to media/module/codecs/amrwb/enc/inc/cod_main.h
diff --git a/media/codecs/amrwb/enc/inc/dtx.h b/media/module/codecs/amrwb/enc/inc/dtx.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/dtx.h
rename to media/module/codecs/amrwb/enc/inc/dtx.h
diff --git a/media/codecs/amrwb/enc/inc/grid100.tab b/media/module/codecs/amrwb/enc/inc/grid100.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/grid100.tab
rename to media/module/codecs/amrwb/enc/inc/grid100.tab
diff --git a/media/codecs/amrwb/enc/inc/ham_wind.tab b/media/module/codecs/amrwb/enc/inc/ham_wind.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/ham_wind.tab
rename to media/module/codecs/amrwb/enc/inc/ham_wind.tab
diff --git a/media/codecs/amrwb/enc/inc/homing.tab b/media/module/codecs/amrwb/enc/inc/homing.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/homing.tab
rename to media/module/codecs/amrwb/enc/inc/homing.tab
diff --git a/media/codecs/amrwb/enc/inc/isp_isf.tab b/media/module/codecs/amrwb/enc/inc/isp_isf.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/isp_isf.tab
rename to media/module/codecs/amrwb/enc/inc/isp_isf.tab
diff --git a/media/codecs/amrwb/enc/inc/lag_wind.tab b/media/module/codecs/amrwb/enc/inc/lag_wind.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/lag_wind.tab
rename to media/module/codecs/amrwb/enc/inc/lag_wind.tab
diff --git a/media/codecs/amrwb/enc/inc/log2.h b/media/module/codecs/amrwb/enc/inc/log2.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/log2.h
rename to media/module/codecs/amrwb/enc/inc/log2.h
diff --git a/media/codecs/amrwb/enc/inc/log2_tab.h b/media/module/codecs/amrwb/enc/inc/log2_tab.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/log2_tab.h
rename to media/module/codecs/amrwb/enc/inc/log2_tab.h
diff --git a/media/codecs/amrwb/enc/inc/main.h b/media/module/codecs/amrwb/enc/inc/main.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/main.h
rename to media/module/codecs/amrwb/enc/inc/main.h
diff --git a/media/codecs/amrwb/enc/inc/math_op.h b/media/module/codecs/amrwb/enc/inc/math_op.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/math_op.h
rename to media/module/codecs/amrwb/enc/inc/math_op.h
diff --git a/media/codecs/amrwb/enc/inc/mem_align.h b/media/module/codecs/amrwb/enc/inc/mem_align.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/mem_align.h
rename to media/module/codecs/amrwb/enc/inc/mem_align.h
diff --git a/media/codecs/amrwb/enc/inc/mime_io.tab b/media/module/codecs/amrwb/enc/inc/mime_io.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/mime_io.tab
rename to media/module/codecs/amrwb/enc/inc/mime_io.tab
diff --git a/media/codecs/amrwb/enc/inc/oper_32b.h b/media/module/codecs/amrwb/enc/inc/oper_32b.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/oper_32b.h
rename to media/module/codecs/amrwb/enc/inc/oper_32b.h
diff --git a/media/codecs/amrwb/enc/inc/p_med_o.h b/media/module/codecs/amrwb/enc/inc/p_med_o.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/p_med_o.h
rename to media/module/codecs/amrwb/enc/inc/p_med_o.h
diff --git a/media/codecs/amrwb/enc/inc/p_med_ol.tab b/media/module/codecs/amrwb/enc/inc/p_med_ol.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/p_med_ol.tab
rename to media/module/codecs/amrwb/enc/inc/p_med_ol.tab
diff --git a/media/codecs/amrwb/enc/inc/q_gain2.tab b/media/module/codecs/amrwb/enc/inc/q_gain2.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/q_gain2.tab
rename to media/module/codecs/amrwb/enc/inc/q_gain2.tab
diff --git a/media/codecs/amrwb/enc/inc/q_pulse.h b/media/module/codecs/amrwb/enc/inc/q_pulse.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/q_pulse.h
rename to media/module/codecs/amrwb/enc/inc/q_pulse.h
diff --git a/media/codecs/amrwb/enc/inc/qisf_ns.tab b/media/module/codecs/amrwb/enc/inc/qisf_ns.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/qisf_ns.tab
rename to media/module/codecs/amrwb/enc/inc/qisf_ns.tab
diff --git a/media/codecs/amrwb/enc/inc/qpisf_2s.tab b/media/module/codecs/amrwb/enc/inc/qpisf_2s.tab
similarity index 100%
rename from media/codecs/amrwb/enc/inc/qpisf_2s.tab
rename to media/module/codecs/amrwb/enc/inc/qpisf_2s.tab
diff --git a/media/codecs/amrwb/enc/inc/stream.h b/media/module/codecs/amrwb/enc/inc/stream.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/stream.h
rename to media/module/codecs/amrwb/enc/inc/stream.h
diff --git a/media/codecs/amrwb/enc/inc/typedef.h b/media/module/codecs/amrwb/enc/inc/typedef.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/typedef.h
rename to media/module/codecs/amrwb/enc/inc/typedef.h
diff --git a/media/codecs/amrwb/enc/inc/typedefs.h b/media/module/codecs/amrwb/enc/inc/typedefs.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/typedefs.h
rename to media/module/codecs/amrwb/enc/inc/typedefs.h
diff --git a/media/codecs/amrwb/enc/inc/wb_vad.h b/media/module/codecs/amrwb/enc/inc/wb_vad.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/wb_vad.h
rename to media/module/codecs/amrwb/enc/inc/wb_vad.h
diff --git a/media/codecs/amrwb/enc/inc/wb_vad_c.h b/media/module/codecs/amrwb/enc/inc/wb_vad_c.h
similarity index 100%
rename from media/codecs/amrwb/enc/inc/wb_vad_c.h
rename to media/module/codecs/amrwb/enc/inc/wb_vad_c.h
diff --git a/media/codecs/amrwb/enc/patent_disclaimer.txt b/media/module/codecs/amrwb/enc/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/amrwb/enc/patent_disclaimer.txt
rename to media/module/codecs/amrwb/enc/patent_disclaimer.txt
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Deemph_32_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Dot_p_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Filt_6k_7k_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Norm_Corr_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/Syn_filt_32_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/convolve_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/cor_h_vec_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/pred_lt4_1_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/residu_asm_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/scale_sig_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s b/media/module/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV5E/syn_filt_opt.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Deemph_32_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Dot_p_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Filt_6k_7k_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Norm_Corr_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/Syn_filt_32_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/convolve_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/cor_h_vec_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/pred_lt4_1_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/residu_asm_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/scale_sig_neon.s
diff --git a/media/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s b/media/module/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
similarity index 100%
rename from media/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
rename to media/module/codecs/amrwb/enc/src/asm/ARMV7/syn_filt_neon.s
diff --git a/media/codecs/amrwb/enc/src/autocorr.c b/media/module/codecs/amrwb/enc/src/autocorr.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/autocorr.c
rename to media/module/codecs/amrwb/enc/src/autocorr.c
diff --git a/media/codecs/amrwb/enc/src/az_isp.c b/media/module/codecs/amrwb/enc/src/az_isp.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/az_isp.c
rename to media/module/codecs/amrwb/enc/src/az_isp.c
diff --git a/media/codecs/amrwb/enc/src/bits.c b/media/module/codecs/amrwb/enc/src/bits.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/bits.c
rename to media/module/codecs/amrwb/enc/src/bits.c
diff --git a/media/codecs/amrwb/enc/src/c2t64fx.c b/media/module/codecs/amrwb/enc/src/c2t64fx.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/c2t64fx.c
rename to media/module/codecs/amrwb/enc/src/c2t64fx.c
diff --git a/media/codecs/amrwb/enc/src/c4t64fx.c b/media/module/codecs/amrwb/enc/src/c4t64fx.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/c4t64fx.c
rename to media/module/codecs/amrwb/enc/src/c4t64fx.c
diff --git a/media/codecs/amrwb/enc/src/convolve.c b/media/module/codecs/amrwb/enc/src/convolve.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/convolve.c
rename to media/module/codecs/amrwb/enc/src/convolve.c
diff --git a/media/codecs/amrwb/enc/src/cor_h_x.c b/media/module/codecs/amrwb/enc/src/cor_h_x.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/cor_h_x.c
rename to media/module/codecs/amrwb/enc/src/cor_h_x.c
diff --git a/media/codecs/amrwb/enc/src/decim54.c b/media/module/codecs/amrwb/enc/src/decim54.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/decim54.c
rename to media/module/codecs/amrwb/enc/src/decim54.c
diff --git a/media/codecs/amrwb/enc/src/deemph.c b/media/module/codecs/amrwb/enc/src/deemph.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/deemph.c
rename to media/module/codecs/amrwb/enc/src/deemph.c
diff --git a/media/codecs/amrwb/enc/src/dtx.c b/media/module/codecs/amrwb/enc/src/dtx.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/dtx.c
rename to media/module/codecs/amrwb/enc/src/dtx.c
diff --git a/media/codecs/amrwb/enc/src/g_pitch.c b/media/module/codecs/amrwb/enc/src/g_pitch.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/g_pitch.c
rename to media/module/codecs/amrwb/enc/src/g_pitch.c
diff --git a/media/codecs/amrwb/enc/src/gpclip.c b/media/module/codecs/amrwb/enc/src/gpclip.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/gpclip.c
rename to media/module/codecs/amrwb/enc/src/gpclip.c
diff --git a/media/codecs/amrwb/enc/src/homing.c b/media/module/codecs/amrwb/enc/src/homing.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/homing.c
rename to media/module/codecs/amrwb/enc/src/homing.c
diff --git a/media/codecs/amrwb/enc/src/hp400.c b/media/module/codecs/amrwb/enc/src/hp400.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp400.c
rename to media/module/codecs/amrwb/enc/src/hp400.c
diff --git a/media/codecs/amrwb/enc/src/hp50.c b/media/module/codecs/amrwb/enc/src/hp50.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp50.c
rename to media/module/codecs/amrwb/enc/src/hp50.c
diff --git a/media/codecs/amrwb/enc/src/hp6k.c b/media/module/codecs/amrwb/enc/src/hp6k.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp6k.c
rename to media/module/codecs/amrwb/enc/src/hp6k.c
diff --git a/media/codecs/amrwb/enc/src/hp_wsp.c b/media/module/codecs/amrwb/enc/src/hp_wsp.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/hp_wsp.c
rename to media/module/codecs/amrwb/enc/src/hp_wsp.c
diff --git a/media/codecs/amrwb/enc/src/int_lpc.c b/media/module/codecs/amrwb/enc/src/int_lpc.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/int_lpc.c
rename to media/module/codecs/amrwb/enc/src/int_lpc.c
diff --git a/media/codecs/amrwb/enc/src/isp_az.c b/media/module/codecs/amrwb/enc/src/isp_az.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/isp_az.c
rename to media/module/codecs/amrwb/enc/src/isp_az.c
diff --git a/media/codecs/amrwb/enc/src/isp_isf.c b/media/module/codecs/amrwb/enc/src/isp_isf.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/isp_isf.c
rename to media/module/codecs/amrwb/enc/src/isp_isf.c
diff --git a/media/codecs/amrwb/enc/src/lag_wind.c b/media/module/codecs/amrwb/enc/src/lag_wind.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/lag_wind.c
rename to media/module/codecs/amrwb/enc/src/lag_wind.c
diff --git a/media/codecs/amrwb/enc/src/levinson.c b/media/module/codecs/amrwb/enc/src/levinson.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/levinson.c
rename to media/module/codecs/amrwb/enc/src/levinson.c
diff --git a/media/codecs/amrwb/enc/src/log2.c b/media/module/codecs/amrwb/enc/src/log2.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/log2.c
rename to media/module/codecs/amrwb/enc/src/log2.c
diff --git a/media/codecs/amrwb/enc/src/lp_dec2.c b/media/module/codecs/amrwb/enc/src/lp_dec2.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/lp_dec2.c
rename to media/module/codecs/amrwb/enc/src/lp_dec2.c
diff --git a/media/codecs/amrwb/enc/src/math_op.c b/media/module/codecs/amrwb/enc/src/math_op.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/math_op.c
rename to media/module/codecs/amrwb/enc/src/math_op.c
diff --git a/media/codecs/amrwb/enc/src/mem_align.c b/media/module/codecs/amrwb/enc/src/mem_align.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/mem_align.c
rename to media/module/codecs/amrwb/enc/src/mem_align.c
diff --git a/media/codecs/amrwb/enc/src/oper_32b.c b/media/module/codecs/amrwb/enc/src/oper_32b.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/oper_32b.c
rename to media/module/codecs/amrwb/enc/src/oper_32b.c
diff --git a/media/codecs/amrwb/enc/src/p_med_ol.c b/media/module/codecs/amrwb/enc/src/p_med_ol.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/p_med_ol.c
rename to media/module/codecs/amrwb/enc/src/p_med_ol.c
diff --git a/media/codecs/amrwb/enc/src/pit_shrp.c b/media/module/codecs/amrwb/enc/src/pit_shrp.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/pit_shrp.c
rename to media/module/codecs/amrwb/enc/src/pit_shrp.c
diff --git a/media/codecs/amrwb/enc/src/pitch_f4.c b/media/module/codecs/amrwb/enc/src/pitch_f4.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/pitch_f4.c
rename to media/module/codecs/amrwb/enc/src/pitch_f4.c
diff --git a/media/codecs/amrwb/enc/src/pred_lt4.c b/media/module/codecs/amrwb/enc/src/pred_lt4.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/pred_lt4.c
rename to media/module/codecs/amrwb/enc/src/pred_lt4.c
diff --git a/media/codecs/amrwb/enc/src/preemph.c b/media/module/codecs/amrwb/enc/src/preemph.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/preemph.c
rename to media/module/codecs/amrwb/enc/src/preemph.c
diff --git a/media/codecs/amrwb/enc/src/q_gain2.c b/media/module/codecs/amrwb/enc/src/q_gain2.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/q_gain2.c
rename to media/module/codecs/amrwb/enc/src/q_gain2.c
diff --git a/media/codecs/amrwb/enc/src/q_pulse.c b/media/module/codecs/amrwb/enc/src/q_pulse.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/q_pulse.c
rename to media/module/codecs/amrwb/enc/src/q_pulse.c
diff --git a/media/codecs/amrwb/enc/src/qisf_ns.c b/media/module/codecs/amrwb/enc/src/qisf_ns.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/qisf_ns.c
rename to media/module/codecs/amrwb/enc/src/qisf_ns.c
diff --git a/media/codecs/amrwb/enc/src/qpisf_2s.c b/media/module/codecs/amrwb/enc/src/qpisf_2s.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/qpisf_2s.c
rename to media/module/codecs/amrwb/enc/src/qpisf_2s.c
diff --git a/media/codecs/amrwb/enc/src/random.c b/media/module/codecs/amrwb/enc/src/random.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/random.c
rename to media/module/codecs/amrwb/enc/src/random.c
diff --git a/media/codecs/amrwb/enc/src/residu.c b/media/module/codecs/amrwb/enc/src/residu.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/residu.c
rename to media/module/codecs/amrwb/enc/src/residu.c
diff --git a/media/codecs/amrwb/enc/src/scale.c b/media/module/codecs/amrwb/enc/src/scale.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/scale.c
rename to media/module/codecs/amrwb/enc/src/scale.c
diff --git a/media/codecs/amrwb/enc/src/stream.c b/media/module/codecs/amrwb/enc/src/stream.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/stream.c
rename to media/module/codecs/amrwb/enc/src/stream.c
diff --git a/media/codecs/amrwb/enc/src/syn_filt.c b/media/module/codecs/amrwb/enc/src/syn_filt.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/syn_filt.c
rename to media/module/codecs/amrwb/enc/src/syn_filt.c
diff --git a/media/codecs/amrwb/enc/src/updt_tar.c b/media/module/codecs/amrwb/enc/src/updt_tar.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/updt_tar.c
rename to media/module/codecs/amrwb/enc/src/updt_tar.c
diff --git a/media/codecs/amrwb/enc/src/util.c b/media/module/codecs/amrwb/enc/src/util.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/util.c
rename to media/module/codecs/amrwb/enc/src/util.c
diff --git a/media/codecs/amrwb/enc/src/voAMRWBEnc.c b/media/module/codecs/amrwb/enc/src/voAMRWBEnc.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/voAMRWBEnc.c
rename to media/module/codecs/amrwb/enc/src/voAMRWBEnc.c
diff --git a/media/codecs/amrwb/enc/src/voicefac.c b/media/module/codecs/amrwb/enc/src/voicefac.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/voicefac.c
rename to media/module/codecs/amrwb/enc/src/voicefac.c
diff --git a/media/codecs/amrwb/enc/src/wb_vad.c b/media/module/codecs/amrwb/enc/src/wb_vad.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/wb_vad.c
rename to media/module/codecs/amrwb/enc/src/wb_vad.c
diff --git a/media/codecs/amrwb/enc/src/weight_a.c b/media/module/codecs/amrwb/enc/src/weight_a.c
similarity index 100%
rename from media/codecs/amrwb/enc/src/weight_a.c
rename to media/module/codecs/amrwb/enc/src/weight_a.c
diff --git a/media/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h b/media/module/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
similarity index 100%
rename from media/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
rename to media/module/codecs/amrwb/enc/test/AmrwbEncTestEnvironment.h
diff --git a/media/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp b/media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
similarity index 100%
rename from media/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
rename to media/module/codecs/amrwb/enc/test/AmrwbEncoderTest.cpp
diff --git a/media/codecs/amrwb/enc/test/Android.bp b/media/module/codecs/amrwb/enc/test/Android.bp
similarity index 90%
rename from media/codecs/amrwb/enc/test/Android.bp
rename to media/module/codecs/amrwb/enc/test/Android.bp
index 942f6c9..f095d62 100644
--- a/media/codecs/amrwb/enc/test/Android.bp
+++ b/media/module/codecs/amrwb/enc/test/Android.bp
@@ -57,4 +57,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/amrwbenc/test/AmrwbEncoderTest.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/amrwb/enc/test/AndroidTest.xml b/media/module/codecs/amrwb/enc/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/amrwb/enc/test/AndroidTest.xml
rename to media/module/codecs/amrwb/enc/test/AndroidTest.xml
diff --git a/media/codecs/amrwb/enc/test/README.md b/media/module/codecs/amrwb/enc/test/README.md
similarity index 100%
rename from media/codecs/amrwb/enc/test/README.md
rename to media/module/codecs/amrwb/enc/test/README.md
diff --git a/media/libstagefright/codecs/common/Android.bp b/media/module/codecs/common/Android.bp
similarity index 100%
rename from media/libstagefright/codecs/common/Android.bp
rename to media/module/codecs/common/Android.bp
diff --git a/media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2 b/media/module/codecs/common/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/codecs/common/MODULE_LICENSE_APACHE2
rename to media/module/codecs/common/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/codecs/common/NOTICE b/media/module/codecs/common/NOTICE
similarity index 100%
rename from media/libstagefright/codecs/common/NOTICE
rename to media/module/codecs/common/NOTICE
diff --git a/media/libstagefright/codecs/common/cmnMemory.c b/media/module/codecs/common/cmnMemory.c
similarity index 100%
rename from media/libstagefright/codecs/common/cmnMemory.c
rename to media/module/codecs/common/cmnMemory.c
diff --git a/media/libstagefright/codecs/common/include/cmnMemory.h b/media/module/codecs/common/include/cmnMemory.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/cmnMemory.h
rename to media/module/codecs/common/include/cmnMemory.h
diff --git a/media/libstagefright/codecs/common/include/voAAC.h b/media/module/codecs/common/include/voAAC.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voAAC.h
rename to media/module/codecs/common/include/voAAC.h
diff --git a/media/libstagefright/codecs/common/include/voAMRWB.h b/media/module/codecs/common/include/voAMRWB.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voAMRWB.h
rename to media/module/codecs/common/include/voAMRWB.h
diff --git a/media/libstagefright/codecs/common/include/voAudio.h b/media/module/codecs/common/include/voAudio.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voAudio.h
rename to media/module/codecs/common/include/voAudio.h
diff --git a/media/libstagefright/codecs/common/include/voIndex.h b/media/module/codecs/common/include/voIndex.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voIndex.h
rename to media/module/codecs/common/include/voIndex.h
diff --git a/media/libstagefright/codecs/common/include/voMem.h b/media/module/codecs/common/include/voMem.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voMem.h
rename to media/module/codecs/common/include/voMem.h
diff --git a/media/libstagefright/codecs/common/include/voType.h b/media/module/codecs/common/include/voType.h
similarity index 100%
rename from media/libstagefright/codecs/common/include/voType.h
rename to media/module/codecs/common/include/voType.h
diff --git a/media/libstagefright/flac/dec/Android.bp b/media/module/codecs/flac/dec/Android.bp
similarity index 100%
rename from media/libstagefright/flac/dec/Android.bp
rename to media/module/codecs/flac/dec/Android.bp
diff --git a/media/libstagefright/flac/dec/FLACDecoder.cpp b/media/module/codecs/flac/dec/FLACDecoder.cpp
similarity index 100%
rename from media/libstagefright/flac/dec/FLACDecoder.cpp
rename to media/module/codecs/flac/dec/FLACDecoder.cpp
diff --git a/media/libstagefright/flac/dec/FLACDecoder.h b/media/module/codecs/flac/dec/FLACDecoder.h
similarity index 100%
rename from media/libstagefright/flac/dec/FLACDecoder.h
rename to media/module/codecs/flac/dec/FLACDecoder.h
diff --git a/media/libstagefright/flac/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/flac/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/flac/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/flac/dec/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/flac/dec/NOTICE b/media/module/codecs/flac/dec/NOTICE
similarity index 100%
rename from media/libstagefright/flac/dec/NOTICE
rename to media/module/codecs/flac/dec/NOTICE
diff --git a/media/libstagefright/flac/dec/test/Android.bp b/media/module/codecs/flac/dec/test/Android.bp
similarity index 100%
rename from media/libstagefright/flac/dec/test/Android.bp
rename to media/module/codecs/flac/dec/test/Android.bp
diff --git a/media/libstagefright/flac/dec/test/AndroidTest.xml b/media/module/codecs/flac/dec/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/flac/dec/test/AndroidTest.xml
rename to media/module/codecs/flac/dec/test/AndroidTest.xml
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTest.cpp b/media/module/codecs/flac/dec/test/FlacDecoderTest.cpp
similarity index 100%
rename from media/libstagefright/flac/dec/test/FlacDecoderTest.cpp
rename to media/module/codecs/flac/dec/test/FlacDecoderTest.cpp
diff --git a/media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h b/media/module/codecs/flac/dec/test/FlacDecoderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/flac/dec/test/FlacDecoderTestEnvironment.h
rename to media/module/codecs/flac/dec/test/FlacDecoderTestEnvironment.h
diff --git a/media/libstagefright/flac/dec/test/README.md b/media/module/codecs/flac/dec/test/README.md
similarity index 100%
rename from media/libstagefright/flac/dec/test/README.md
rename to media/module/codecs/flac/dec/test/README.md
diff --git a/media/codecs/g711/decoder/Android.bp b/media/module/codecs/g711/decoder/Android.bp
similarity index 100%
rename from media/codecs/g711/decoder/Android.bp
rename to media/module/codecs/g711/decoder/Android.bp
diff --git a/media/codecs/g711/decoder/g711Dec.h b/media/module/codecs/g711/decoder/g711Dec.h
similarity index 100%
rename from media/codecs/g711/decoder/g711Dec.h
rename to media/module/codecs/g711/decoder/g711Dec.h
diff --git a/media/codecs/g711/decoder/g711DecAlaw.cpp b/media/module/codecs/g711/decoder/g711DecAlaw.cpp
similarity index 100%
rename from media/codecs/g711/decoder/g711DecAlaw.cpp
rename to media/module/codecs/g711/decoder/g711DecAlaw.cpp
diff --git a/media/codecs/g711/decoder/g711DecMlaw.cpp b/media/module/codecs/g711/decoder/g711DecMlaw.cpp
similarity index 100%
rename from media/codecs/g711/decoder/g711DecMlaw.cpp
rename to media/module/codecs/g711/decoder/g711DecMlaw.cpp
diff --git a/media/codecs/g711/fuzzer/Android.bp b/media/module/codecs/g711/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/g711/fuzzer/Android.bp
rename to media/module/codecs/g711/fuzzer/Android.bp
diff --git a/media/codecs/g711/fuzzer/README.md b/media/module/codecs/g711/fuzzer/README.md
similarity index 100%
rename from media/codecs/g711/fuzzer/README.md
rename to media/module/codecs/g711/fuzzer/README.md
diff --git a/media/codecs/g711/fuzzer/g711_dec_fuzzer.cpp b/media/module/codecs/g711/fuzzer/g711_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/g711/fuzzer/g711_dec_fuzzer.cpp
rename to media/module/codecs/g711/fuzzer/g711_dec_fuzzer.cpp
diff --git a/media/codecs/m4v_h263/TEST_MAPPING b/media/module/codecs/m4v_h263/TEST_MAPPING
similarity index 100%
rename from media/codecs/m4v_h263/TEST_MAPPING
rename to media/module/codecs/m4v_h263/TEST_MAPPING
diff --git a/media/codecs/m4v_h263/dec/Android.bp b/media/module/codecs/m4v_h263/dec/Android.bp
similarity index 100%
rename from media/codecs/m4v_h263/dec/Android.bp
rename to media/module/codecs/m4v_h263/dec/Android.bp
diff --git a/media/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/m4v_h263/dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/m4v_h263/dec/NOTICE b/media/module/codecs/m4v_h263/dec/NOTICE
similarity index 100%
rename from media/codecs/m4v_h263/dec/NOTICE
rename to media/module/codecs/m4v_h263/dec/NOTICE
diff --git a/media/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h b/media/module/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
rename to media/module/codecs/m4v_h263/dec/include/m4vh263_decoder_pv_types.h
diff --git a/media/codecs/m4v_h263/dec/include/mp4dec_api.h b/media/module/codecs/m4v_h263/dec/include/mp4dec_api.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/include/mp4dec_api.h
rename to media/module/codecs/m4v_h263/dec/include/mp4dec_api.h
diff --git a/media/codecs/m4v_h263/dec/include/visual_header.h b/media/module/codecs/m4v_h263/dec/include/visual_header.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/include/visual_header.h
rename to media/module/codecs/m4v_h263/dec/include/visual_header.h
diff --git a/media/codecs/m4v_h263/dec/src/bitstream.cpp b/media/module/codecs/m4v_h263/dec/src/bitstream.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/bitstream.cpp
rename to media/module/codecs/m4v_h263/dec/src/bitstream.cpp
diff --git a/media/codecs/m4v_h263/dec/src/bitstream.h b/media/module/codecs/m4v_h263/dec/src/bitstream.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/bitstream.h
rename to media/module/codecs/m4v_h263/dec/src/bitstream.h
diff --git a/media/codecs/m4v_h263/dec/src/block_idct.cpp b/media/module/codecs/m4v_h263/dec/src/block_idct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/block_idct.cpp
rename to media/module/codecs/m4v_h263/dec/src/block_idct.cpp
diff --git a/media/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp b/media/module/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
rename to media/module/codecs/m4v_h263/dec/src/cal_dc_scaler.cpp
diff --git a/media/codecs/m4v_h263/dec/src/combined_decode.cpp b/media/module/codecs/m4v_h263/dec/src/combined_decode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/combined_decode.cpp
rename to media/module/codecs/m4v_h263/dec/src/combined_decode.cpp
diff --git a/media/codecs/m4v_h263/dec/src/conceal.cpp b/media/module/codecs/m4v_h263/dec/src/conceal.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/conceal.cpp
rename to media/module/codecs/m4v_h263/dec/src/conceal.cpp
diff --git a/media/codecs/m4v_h263/dec/src/datapart_decode.cpp b/media/module/codecs/m4v_h263/dec/src/datapart_decode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/datapart_decode.cpp
rename to media/module/codecs/m4v_h263/dec/src/datapart_decode.cpp
diff --git a/media/codecs/m4v_h263/dec/src/dcac_prediction.cpp b/media/module/codecs/m4v_h263/dec/src/dcac_prediction.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/dcac_prediction.cpp
rename to media/module/codecs/m4v_h263/dec/src/dcac_prediction.cpp
diff --git a/media/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp b/media/module/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
rename to media/module/codecs/m4v_h263/dec/src/dec_pred_intra_dc.cpp
diff --git a/media/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp b/media/module/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
rename to media/module/codecs/m4v_h263/dec/src/get_pred_adv_b_add.cpp
diff --git a/media/codecs/m4v_h263/dec/src/get_pred_outside.cpp b/media/module/codecs/m4v_h263/dec/src/get_pred_outside.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/get_pred_outside.cpp
rename to media/module/codecs/m4v_h263/dec/src/get_pred_outside.cpp
diff --git a/media/codecs/m4v_h263/dec/src/idct.cpp b/media/module/codecs/m4v_h263/dec/src/idct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/idct.cpp
rename to media/module/codecs/m4v_h263/dec/src/idct.cpp
diff --git a/media/codecs/m4v_h263/dec/src/idct.h b/media/module/codecs/m4v_h263/dec/src/idct.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/idct.h
rename to media/module/codecs/m4v_h263/dec/src/idct.h
diff --git a/media/codecs/m4v_h263/dec/src/idct_vca.cpp b/media/module/codecs/m4v_h263/dec/src/idct_vca.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/idct_vca.cpp
rename to media/module/codecs/m4v_h263/dec/src/idct_vca.cpp
diff --git a/media/codecs/m4v_h263/dec/src/max_level.h b/media/module/codecs/m4v_h263/dec/src/max_level.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/max_level.h
rename to media/module/codecs/m4v_h263/dec/src/max_level.h
diff --git a/media/codecs/m4v_h263/dec/src/mb_motion_comp.cpp b/media/module/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
rename to media/module/codecs/m4v_h263/dec/src/mb_motion_comp.cpp
diff --git a/media/codecs/m4v_h263/dec/src/mb_utils.cpp b/media/module/codecs/m4v_h263/dec/src/mb_utils.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mb_utils.cpp
rename to media/module/codecs/m4v_h263/dec/src/mb_utils.cpp
diff --git a/media/codecs/m4v_h263/dec/src/mbtype_mode.h b/media/module/codecs/m4v_h263/dec/src/mbtype_mode.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mbtype_mode.h
rename to media/module/codecs/m4v_h263/dec/src/mbtype_mode.h
diff --git a/media/codecs/m4v_h263/dec/src/motion_comp.h b/media/module/codecs/m4v_h263/dec/src/motion_comp.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/motion_comp.h
rename to media/module/codecs/m4v_h263/dec/src/motion_comp.h
diff --git a/media/codecs/m4v_h263/dec/src/mp4dec_lib.h b/media/module/codecs/m4v_h263/dec/src/mp4dec_lib.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mp4dec_lib.h
rename to media/module/codecs/m4v_h263/dec/src/mp4dec_lib.h
diff --git a/media/codecs/m4v_h263/dec/src/mp4def.h b/media/module/codecs/m4v_h263/dec/src/mp4def.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mp4def.h
rename to media/module/codecs/m4v_h263/dec/src/mp4def.h
diff --git a/media/codecs/m4v_h263/dec/src/mp4lib_int.h b/media/module/codecs/m4v_h263/dec/src/mp4lib_int.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/mp4lib_int.h
rename to media/module/codecs/m4v_h263/dec/src/mp4lib_int.h
diff --git a/media/codecs/m4v_h263/dec/src/packet_util.cpp b/media/module/codecs/m4v_h263/dec/src/packet_util.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/packet_util.cpp
rename to media/module/codecs/m4v_h263/dec/src/packet_util.cpp
diff --git a/media/codecs/m4v_h263/dec/src/post_filter.cpp b/media/module/codecs/m4v_h263/dec/src/post_filter.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/post_filter.cpp
rename to media/module/codecs/m4v_h263/dec/src/post_filter.cpp
diff --git a/media/codecs/m4v_h263/dec/src/post_proc.h b/media/module/codecs/m4v_h263/dec/src/post_proc.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/post_proc.h
rename to media/module/codecs/m4v_h263/dec/src/post_proc.h
diff --git a/media/codecs/m4v_h263/dec/src/pvdec_api.cpp b/media/module/codecs/m4v_h263/dec/src/pvdec_api.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/pvdec_api.cpp
rename to media/module/codecs/m4v_h263/dec/src/pvdec_api.cpp
diff --git a/media/codecs/m4v_h263/dec/src/scaling.h b/media/module/codecs/m4v_h263/dec/src/scaling.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/scaling.h
rename to media/module/codecs/m4v_h263/dec/src/scaling.h
diff --git a/media/codecs/m4v_h263/dec/src/scaling_tab.cpp b/media/module/codecs/m4v_h263/dec/src/scaling_tab.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/scaling_tab.cpp
rename to media/module/codecs/m4v_h263/dec/src/scaling_tab.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vlc_dec_tab.h b/media/module/codecs/m4v_h263/dec/src/vlc_dec_tab.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_dec_tab.h
rename to media/module/codecs/m4v_h263/dec/src/vlc_dec_tab.h
diff --git a/media/codecs/m4v_h263/dec/src/vlc_decode.cpp b/media/module/codecs/m4v_h263/dec/src/vlc_decode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_decode.cpp
rename to media/module/codecs/m4v_h263/dec/src/vlc_decode.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vlc_decode.h b/media/module/codecs/m4v_h263/dec/src/vlc_decode.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_decode.h
rename to media/module/codecs/m4v_h263/dec/src/vlc_decode.h
diff --git a/media/codecs/m4v_h263/dec/src/vlc_dequant.cpp b/media/module/codecs/m4v_h263/dec/src/vlc_dequant.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_dequant.cpp
rename to media/module/codecs/m4v_h263/dec/src/vlc_dequant.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vlc_tab.cpp b/media/module/codecs/m4v_h263/dec/src/vlc_tab.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vlc_tab.cpp
rename to media/module/codecs/m4v_h263/dec/src/vlc_tab.cpp
diff --git a/media/codecs/m4v_h263/dec/src/vop.cpp b/media/module/codecs/m4v_h263/dec/src/vop.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/vop.cpp
rename to media/module/codecs/m4v_h263/dec/src/vop.cpp
diff --git a/media/codecs/m4v_h263/dec/src/zigzag.h b/media/module/codecs/m4v_h263/dec/src/zigzag.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/zigzag.h
rename to media/module/codecs/m4v_h263/dec/src/zigzag.h
diff --git a/media/codecs/m4v_h263/dec/src/zigzag_tab.cpp b/media/module/codecs/m4v_h263/dec/src/zigzag_tab.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/src/zigzag_tab.cpp
rename to media/module/codecs/m4v_h263/dec/src/zigzag_tab.cpp
diff --git a/media/codecs/m4v_h263/dec/test/Android.bp b/media/module/codecs/m4v_h263/dec/test/Android.bp
similarity index 92%
rename from media/codecs/m4v_h263/dec/test/Android.bp
rename to media/module/codecs/m4v_h263/dec/test/Android.bp
index d8de569..9dc756c 100644
--- a/media/codecs/m4v_h263/dec/test/Android.bp
+++ b/media/module/codecs/m4v_h263/dec/test/Android.bp
@@ -76,4 +76,7 @@
         ],
         cfi: true,
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/dec/test/Mpeg4H263Decoder-1.1.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/m4v_h263/dec/test/AndroidTest.xml b/media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/AndroidTest.xml
rename to media/module/codecs/m4v_h263/dec/test/AndroidTest.xml
diff --git a/media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp b/media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
rename to media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTest.cpp
diff --git a/media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h b/media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
rename to media/module/codecs/m4v_h263/dec/test/Mpeg4H263DecoderTestEnvironment.h
diff --git a/media/codecs/m4v_h263/dec/test/README.md b/media/module/codecs/m4v_h263/dec/test/README.md
similarity index 100%
rename from media/codecs/m4v_h263/dec/test/README.md
rename to media/module/codecs/m4v_h263/dec/test/README.md
diff --git a/media/codecs/m4v_h263/enc/Android.bp b/media/module/codecs/m4v_h263/enc/Android.bp
similarity index 100%
rename from media/codecs/m4v_h263/enc/Android.bp
rename to media/module/codecs/m4v_h263/enc/Android.bp
diff --git a/media/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2 b/media/module/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
rename to media/module/codecs/m4v_h263/enc/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/m4v_h263/enc/NOTICE b/media/module/codecs/m4v_h263/enc/NOTICE
similarity index 100%
rename from media/codecs/m4v_h263/enc/NOTICE
rename to media/module/codecs/m4v_h263/enc/NOTICE
diff --git a/media/codecs/m4v_h263/enc/include/cvei.h b/media/module/codecs/m4v_h263/enc/include/cvei.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/include/cvei.h
rename to media/module/codecs/m4v_h263/enc/include/cvei.h
diff --git a/media/codecs/m4v_h263/enc/include/mp4enc_api.h b/media/module/codecs/m4v_h263/enc/include/mp4enc_api.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/include/mp4enc_api.h
rename to media/module/codecs/m4v_h263/enc/include/mp4enc_api.h
diff --git a/media/codecs/m4v_h263/enc/src/bitstream_io.cpp b/media/module/codecs/m4v_h263/enc/src/bitstream_io.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/bitstream_io.cpp
rename to media/module/codecs/m4v_h263/enc/src/bitstream_io.cpp
diff --git a/media/codecs/m4v_h263/enc/src/bitstream_io.h b/media/module/codecs/m4v_h263/enc/src/bitstream_io.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/bitstream_io.h
rename to media/module/codecs/m4v_h263/enc/src/bitstream_io.h
diff --git a/media/codecs/m4v_h263/enc/src/combined_encode.cpp b/media/module/codecs/m4v_h263/enc/src/combined_encode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/combined_encode.cpp
rename to media/module/codecs/m4v_h263/enc/src/combined_encode.cpp
diff --git a/media/codecs/m4v_h263/enc/src/datapart_encode.cpp b/media/module/codecs/m4v_h263/enc/src/datapart_encode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/datapart_encode.cpp
rename to media/module/codecs/m4v_h263/enc/src/datapart_encode.cpp
diff --git a/media/codecs/m4v_h263/enc/src/dct.cpp b/media/module/codecs/m4v_h263/enc/src/dct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/dct.cpp
rename to media/module/codecs/m4v_h263/enc/src/dct.cpp
diff --git a/media/codecs/m4v_h263/enc/src/dct.h b/media/module/codecs/m4v_h263/enc/src/dct.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/dct.h
rename to media/module/codecs/m4v_h263/enc/src/dct.h
diff --git a/media/codecs/m4v_h263/enc/src/dct_inline.h b/media/module/codecs/m4v_h263/enc/src/dct_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/dct_inline.h
rename to media/module/codecs/m4v_h263/enc/src/dct_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/fastcodemb.cpp b/media/module/codecs/m4v_h263/enc/src/fastcodemb.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastcodemb.cpp
rename to media/module/codecs/m4v_h263/enc/src/fastcodemb.cpp
diff --git a/media/codecs/m4v_h263/enc/src/fastcodemb.h b/media/module/codecs/m4v_h263/enc/src/fastcodemb.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastcodemb.h
rename to media/module/codecs/m4v_h263/enc/src/fastcodemb.h
diff --git a/media/codecs/m4v_h263/enc/src/fastidct.cpp b/media/module/codecs/m4v_h263/enc/src/fastidct.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastidct.cpp
rename to media/module/codecs/m4v_h263/enc/src/fastidct.cpp
diff --git a/media/codecs/m4v_h263/enc/src/fastquant.cpp b/media/module/codecs/m4v_h263/enc/src/fastquant.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastquant.cpp
rename to media/module/codecs/m4v_h263/enc/src/fastquant.cpp
diff --git a/media/codecs/m4v_h263/enc/src/fastquant_inline.h b/media/module/codecs/m4v_h263/enc/src/fastquant_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/fastquant_inline.h
rename to media/module/codecs/m4v_h263/enc/src/fastquant_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/findhalfpel.cpp b/media/module/codecs/m4v_h263/enc/src/findhalfpel.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/findhalfpel.cpp
rename to media/module/codecs/m4v_h263/enc/src/findhalfpel.cpp
diff --git a/media/codecs/m4v_h263/enc/src/m4venc_oscl.h b/media/module/codecs/m4v_h263/enc/src/m4venc_oscl.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/m4venc_oscl.h
rename to media/module/codecs/m4v_h263/enc/src/m4venc_oscl.h
diff --git a/media/codecs/m4v_h263/enc/src/me_utils.cpp b/media/module/codecs/m4v_h263/enc/src/me_utils.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/me_utils.cpp
rename to media/module/codecs/m4v_h263/enc/src/me_utils.cpp
diff --git a/media/codecs/m4v_h263/enc/src/motion_comp.cpp b/media/module/codecs/m4v_h263/enc/src/motion_comp.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/motion_comp.cpp
rename to media/module/codecs/m4v_h263/enc/src/motion_comp.cpp
diff --git a/media/codecs/m4v_h263/enc/src/motion_est.cpp b/media/module/codecs/m4v_h263/enc/src/motion_est.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/motion_est.cpp
rename to media/module/codecs/m4v_h263/enc/src/motion_est.cpp
diff --git a/media/codecs/m4v_h263/enc/src/mp4def.h b/media/module/codecs/m4v_h263/enc/src/mp4def.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4def.h
rename to media/module/codecs/m4v_h263/enc/src/mp4def.h
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_api.cpp b/media/module/codecs/m4v_h263/enc/src/mp4enc_api.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4enc_api.cpp
rename to media/module/codecs/m4v_h263/enc/src/mp4enc_api.cpp
diff --git a/media/codecs/m4v_h263/enc/src/mp4enc_lib.h b/media/module/codecs/m4v_h263/enc/src/mp4enc_lib.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4enc_lib.h
rename to media/module/codecs/m4v_h263/enc/src/mp4enc_lib.h
diff --git a/media/codecs/m4v_h263/enc/src/mp4lib_int.h b/media/module/codecs/m4v_h263/enc/src/mp4lib_int.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/mp4lib_int.h
rename to media/module/codecs/m4v_h263/enc/src/mp4lib_int.h
diff --git a/media/codecs/m4v_h263/enc/src/rate_control.cpp b/media/module/codecs/m4v_h263/enc/src/rate_control.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/rate_control.cpp
rename to media/module/codecs/m4v_h263/enc/src/rate_control.cpp
diff --git a/media/codecs/m4v_h263/enc/src/rate_control.h b/media/module/codecs/m4v_h263/enc/src/rate_control.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/rate_control.h
rename to media/module/codecs/m4v_h263/enc/src/rate_control.h
diff --git a/media/codecs/m4v_h263/enc/src/sad.cpp b/media/module/codecs/m4v_h263/enc/src/sad.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad.cpp
rename to media/module/codecs/m4v_h263/enc/src/sad.cpp
diff --git a/media/codecs/m4v_h263/enc/src/sad_halfpel.cpp b/media/module/codecs/m4v_h263/enc/src/sad_halfpel.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_halfpel.cpp
rename to media/module/codecs/m4v_h263/enc/src/sad_halfpel.cpp
diff --git a/media/codecs/m4v_h263/enc/src/sad_halfpel_inline.h b/media/module/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
rename to media/module/codecs/m4v_h263/enc/src/sad_halfpel_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/sad_inline.h b/media/module/codecs/m4v_h263/enc/src/sad_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_inline.h
rename to media/module/codecs/m4v_h263/enc/src/sad_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/sad_mb_offset.h b/media/module/codecs/m4v_h263/enc/src/sad_mb_offset.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/sad_mb_offset.h
rename to media/module/codecs/m4v_h263/enc/src/sad_mb_offset.h
diff --git a/media/codecs/m4v_h263/enc/src/vlc_enc_tab.h b/media/module/codecs/m4v_h263/enc/src/vlc_enc_tab.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_enc_tab.h
rename to media/module/codecs/m4v_h263/enc/src/vlc_enc_tab.h
diff --git a/media/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/module/codecs/m4v_h263/enc/src/vlc_encode.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_encode.cpp
rename to media/module/codecs/m4v_h263/enc/src/vlc_encode.cpp
diff --git a/media/codecs/m4v_h263/enc/src/vlc_encode.h b/media/module/codecs/m4v_h263/enc/src/vlc_encode.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_encode.h
rename to media/module/codecs/m4v_h263/enc/src/vlc_encode.h
diff --git a/media/codecs/m4v_h263/enc/src/vlc_encode_inline.h b/media/module/codecs/m4v_h263/enc/src/vlc_encode_inline.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vlc_encode_inline.h
rename to media/module/codecs/m4v_h263/enc/src/vlc_encode_inline.h
diff --git a/media/codecs/m4v_h263/enc/src/vop.cpp b/media/module/codecs/m4v_h263/enc/src/vop.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/src/vop.cpp
rename to media/module/codecs/m4v_h263/enc/src/vop.cpp
diff --git a/media/codecs/m4v_h263/enc/test/Android.bp b/media/module/codecs/m4v_h263/enc/test/Android.bp
similarity index 90%
rename from media/codecs/m4v_h263/enc/test/Android.bp
rename to media/module/codecs/m4v_h263/enc/test/Android.bp
index 2b5e49c..d75e2d1 100644
--- a/media/codecs/m4v_h263/enc/test/Android.bp
+++ b/media/module/codecs/m4v_h263/enc/test/Android.bp
@@ -55,4 +55,7 @@
         ],
         cfi: true,
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/codecs/m4v_h263/enc/test/Mpeg4H263Encoder.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/m4v_h263/enc/test/AndroidTest.xml b/media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/AndroidTest.xml
rename to media/module/codecs/m4v_h263/enc/test/AndroidTest.xml
diff --git a/media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp b/media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
rename to media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTest.cpp
diff --git a/media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h b/media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
rename to media/module/codecs/m4v_h263/enc/test/Mpeg4H263EncoderTestEnvironment.h
diff --git a/media/codecs/m4v_h263/enc/test/README.md b/media/module/codecs/m4v_h263/enc/test/README.md
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/README.md
rename to media/module/codecs/m4v_h263/enc/test/README.md
diff --git a/media/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp b/media/module/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
similarity index 100%
rename from media/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
rename to media/module/codecs/m4v_h263/enc/test/m4v_h263_enc_test.cpp
diff --git a/media/codecs/m4v_h263/fuzzer/Android.bp b/media/module/codecs/m4v_h263/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/Android.bp
rename to media/module/codecs/m4v_h263/fuzzer/Android.bp
diff --git a/media/codecs/m4v_h263/fuzzer/README.md b/media/module/codecs/m4v_h263/fuzzer/README.md
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/README.md
rename to media/module/codecs/m4v_h263/fuzzer/README.md
diff --git a/media/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict b/media/module/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
rename to media/module/codecs/m4v_h263/fuzzer/h263_dec_fuzzer.dict
diff --git a/media/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict b/media/module/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
rename to media/module/codecs/m4v_h263/fuzzer/mpeg4_dec_fuzzer.dict
diff --git a/media/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp b/media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
rename to media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_dec_fuzzer.cpp
diff --git a/media/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp b/media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
similarity index 100%
rename from media/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
rename to media/module/codecs/m4v_h263/fuzzer/mpeg4_h263_enc_fuzzer.cpp
diff --git a/media/codecs/m4v_h263/patent_disclaimer.txt b/media/module/codecs/m4v_h263/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/m4v_h263/patent_disclaimer.txt
rename to media/module/codecs/m4v_h263/patent_disclaimer.txt
diff --git a/media/codecs/mp3dec/Android.bp b/media/module/codecs/mp3dec/Android.bp
similarity index 100%
rename from media/codecs/mp3dec/Android.bp
rename to media/module/codecs/mp3dec/Android.bp
diff --git a/media/codecs/mp3dec/MODULE_LICENSE_APACHE2 b/media/module/codecs/mp3dec/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/codecs/mp3dec/MODULE_LICENSE_APACHE2
rename to media/module/codecs/mp3dec/MODULE_LICENSE_APACHE2
diff --git a/media/codecs/mp3dec/NOTICE b/media/module/codecs/mp3dec/NOTICE
similarity index 100%
rename from media/codecs/mp3dec/NOTICE
rename to media/module/codecs/mp3dec/NOTICE
diff --git a/media/codecs/mp3dec/TEST_MAPPING b/media/module/codecs/mp3dec/TEST_MAPPING
similarity index 100%
rename from media/codecs/mp3dec/TEST_MAPPING
rename to media/module/codecs/mp3dec/TEST_MAPPING
diff --git a/media/codecs/mp3dec/fuzzer/Android.bp b/media/module/codecs/mp3dec/fuzzer/Android.bp
similarity index 100%
rename from media/codecs/mp3dec/fuzzer/Android.bp
rename to media/module/codecs/mp3dec/fuzzer/Android.bp
diff --git a/media/codecs/mp3dec/fuzzer/README.md b/media/module/codecs/mp3dec/fuzzer/README.md
similarity index 100%
rename from media/codecs/mp3dec/fuzzer/README.md
rename to media/module/codecs/mp3dec/fuzzer/README.md
diff --git a/media/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp b/media/module/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
similarity index 100%
rename from media/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
rename to media/module/codecs/mp3dec/fuzzer/mp3_dec_fuzzer.cpp
diff --git a/media/codecs/mp3dec/include/mp3_decoder_selection.h b/media/module/codecs/mp3dec/include/mp3_decoder_selection.h
similarity index 100%
rename from media/codecs/mp3dec/include/mp3_decoder_selection.h
rename to media/module/codecs/mp3dec/include/mp3_decoder_selection.h
diff --git a/media/codecs/mp3dec/include/pvmp3_audio_type_defs.h b/media/module/codecs/mp3dec/include/pvmp3_audio_type_defs.h
similarity index 100%
rename from media/codecs/mp3dec/include/pvmp3_audio_type_defs.h
rename to media/module/codecs/mp3dec/include/pvmp3_audio_type_defs.h
diff --git a/media/codecs/mp3dec/include/pvmp3decoder_api.h b/media/module/codecs/mp3dec/include/pvmp3decoder_api.h
similarity index 100%
rename from media/codecs/mp3dec/include/pvmp3decoder_api.h
rename to media/module/codecs/mp3dec/include/pvmp3decoder_api.h
diff --git a/media/codecs/mp3dec/patent_disclaimer.txt b/media/module/codecs/mp3dec/patent_disclaimer.txt
similarity index 100%
rename from media/codecs/mp3dec/patent_disclaimer.txt
rename to media/module/codecs/mp3dec/patent_disclaimer.txt
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_dct_16_gcc.s
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_dct_9_gcc.s
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_mdct_18_gcc.s
diff --git a/media/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s b/media/module/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
similarity index 100%
rename from media/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
rename to media/module/codecs/mp3dec/src/asm/pvmp3_polyphase_filter_window_gcc.s
diff --git a/media/codecs/mp3dec/src/mp3_mem_funcs.h b/media/module/codecs/mp3dec/src/mp3_mem_funcs.h
similarity index 100%
rename from media/codecs/mp3dec/src/mp3_mem_funcs.h
rename to media/module/codecs/mp3dec/src/mp3_mem_funcs.h
diff --git a/media/codecs/mp3dec/src/pv_mp3_huffman.h b/media/module/codecs/mp3dec/src/pv_mp3_huffman.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3_huffman.h
rename to media/module/codecs/mp3dec/src/pv_mp3_huffman.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_arm_gcc.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_c_equivalent.h
diff --git a/media/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h b/media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
rename to media/module/codecs/mp3dec/src/pv_mp3dec_fxd_op_msc_evc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_alias_reduction.cpp b/media/module/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_alias_reduction.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_alias_reduction.h b/media/module/codecs/mp3dec/src/pvmp3_alias_reduction.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_alias_reduction.h
rename to media/module/codecs/mp3dec/src/pvmp3_alias_reduction.h
diff --git a/media/codecs/mp3dec/src/pvmp3_crc.cpp b/media/module/codecs/mp3dec/src/pvmp3_crc.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_crc.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_crc.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_crc.h b/media/module/codecs/mp3dec/src/pvmp3_crc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_crc.h
rename to media/module/codecs/mp3dec/src/pvmp3_crc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_16.cpp b/media/module/codecs/mp3dec/src/pvmp3_dct_16.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_16.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dct_16.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_16.h b/media/module/codecs/mp3dec/src/pvmp3_dct_16.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_16.h
rename to media/module/codecs/mp3dec/src/pvmp3_dct_16.h
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_6.cpp b/media/module/codecs/mp3dec/src/pvmp3_dct_6.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_6.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dct_6.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dct_9.cpp b/media/module/codecs/mp3dec/src/pvmp3_dct_9.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dct_9.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dct_9.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dec_defs.h b/media/module/codecs/mp3dec/src/pvmp3_dec_defs.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dec_defs.h
rename to media/module/codecs/mp3dec/src/pvmp3_dec_defs.h
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_header.cpp b/media/module/codecs/mp3dec/src/pvmp3_decode_header.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_header.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_decode_header.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_header.h b/media/module/codecs/mp3dec/src/pvmp3_decode_header.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_header.h
rename to media/module/codecs/mp3dec/src/pvmp3_decode_header.h
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp b/media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_decode_huff_cw.h b/media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
rename to media/module/codecs/mp3dec/src/pvmp3_decode_huff_cw.h
diff --git a/media/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp b/media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_dequantize_sample.h b/media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_dequantize_sample.h
rename to media/module/codecs/mp3dec/src/pvmp3_dequantize_sample.h
diff --git a/media/codecs/mp3dec/src/pvmp3_equalizer.cpp b/media/module/codecs/mp3dec/src/pvmp3_equalizer.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_equalizer.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_equalizer.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_equalizer.h b/media/module/codecs/mp3dec/src/pvmp3_equalizer.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_equalizer.h
rename to media/module/codecs/mp3dec/src/pvmp3_equalizer.h
diff --git a/media/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/module/codecs/mp3dec/src/pvmp3_framedecoder.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_framedecoder.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_framedecoder.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_framedecoder.h b/media/module/codecs/mp3dec/src/pvmp3_framedecoder.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_framedecoder.h
rename to media/module/codecs/mp3dec/src/pvmp3_framedecoder.h
diff --git a/media/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp b/media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_get_main_data_size.h b/media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_main_data_size.h
rename to media/module/codecs/mp3dec/src/pvmp3_get_main_data_size.h
diff --git a/media/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp b/media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_get_scale_factors.h b/media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_scale_factors.h
rename to media/module/codecs/mp3dec/src/pvmp3_get_scale_factors.h
diff --git a/media/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/module/codecs/mp3dec/src/pvmp3_get_side_info.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_side_info.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_get_side_info.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_get_side_info.h b/media/module/codecs/mp3dec/src/pvmp3_get_side_info.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_get_side_info.h
rename to media/module/codecs/mp3dec/src/pvmp3_get_side_info.h
diff --git a/media/codecs/mp3dec/src/pvmp3_getbits.cpp b/media/module/codecs/mp3dec/src/pvmp3_getbits.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_getbits.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_getbits.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_getbits.h b/media/module/codecs/mp3dec/src/pvmp3_getbits.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_getbits.h
rename to media/module/codecs/mp3dec/src/pvmp3_getbits.h
diff --git a/media/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp b/media/module/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_huffman_decoding.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp b/media/module/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_huffman_parsing.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_imdct_synth.cpp b/media/module/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_imdct_synth.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_imdct_synth.h b/media/module/codecs/mp3dec/src/pvmp3_imdct_synth.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_imdct_synth.h
rename to media/module/codecs/mp3dec/src/pvmp3_imdct_synth.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_18.cpp b/media/module/codecs/mp3dec/src/pvmp3_mdct_18.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_18.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_18.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_18.h b/media/module/codecs/mp3dec/src/pvmp3_mdct_18.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_18.h
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_18.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_6.cpp b/media/module/codecs/mp3dec/src/pvmp3_mdct_6.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_6.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_6.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mdct_6.h b/media/module/codecs/mp3dec/src/pvmp3_mdct_6.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mdct_6.h
rename to media/module/codecs/mp3dec/src/pvmp3_mdct_6.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_data.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_get_scale_factors.h
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h b/media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
rename to media/module/codecs/mp3dec/src/pvmp3_mpeg2_stereo_proc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_normalize.cpp b/media/module/codecs/mp3dec/src/pvmp3_normalize.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_normalize.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_normalize.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_normalize.h b/media/module/codecs/mp3dec/src/pvmp3_normalize.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_normalize.h
rename to media/module/codecs/mp3dec/src/pvmp3_normalize.h
diff --git a/media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp b/media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h b/media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
rename to media/module/codecs/mp3dec/src/pvmp3_poly_phase_synthesis.h
diff --git a/media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp b/media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h b/media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
rename to media/module/codecs/mp3dec/src/pvmp3_polyphase_filter_window.h
diff --git a/media/codecs/mp3dec/src/pvmp3_reorder.cpp b/media/module/codecs/mp3dec/src/pvmp3_reorder.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_reorder.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_reorder.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_reorder.h b/media/module/codecs/mp3dec/src/pvmp3_reorder.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_reorder.h
rename to media/module/codecs/mp3dec/src/pvmp3_reorder.h
diff --git a/media/codecs/mp3dec/src/pvmp3_seek_synch.cpp b/media/module/codecs/mp3dec/src/pvmp3_seek_synch.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_seek_synch.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_seek_synch.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_seek_synch.h b/media/module/codecs/mp3dec/src/pvmp3_seek_synch.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_seek_synch.h
rename to media/module/codecs/mp3dec/src/pvmp3_seek_synch.h
diff --git a/media/codecs/mp3dec/src/pvmp3_stereo_proc.cpp b/media/module/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_stereo_proc.h b/media/module/codecs/mp3dec/src/pvmp3_stereo_proc.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_stereo_proc.h
rename to media/module/codecs/mp3dec/src/pvmp3_stereo_proc.h
diff --git a/media/codecs/mp3dec/src/pvmp3_tables.cpp b/media/module/codecs/mp3dec/src/pvmp3_tables.cpp
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_tables.cpp
rename to media/module/codecs/mp3dec/src/pvmp3_tables.cpp
diff --git a/media/codecs/mp3dec/src/pvmp3_tables.h b/media/module/codecs/mp3dec/src/pvmp3_tables.h
similarity index 100%
rename from media/codecs/mp3dec/src/pvmp3_tables.h
rename to media/module/codecs/mp3dec/src/pvmp3_tables.h
diff --git a/media/codecs/mp3dec/src/s_huffcodetab.h b/media/module/codecs/mp3dec/src/s_huffcodetab.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_huffcodetab.h
rename to media/module/codecs/mp3dec/src/s_huffcodetab.h
diff --git a/media/codecs/mp3dec/src/s_mp3bits.h b/media/module/codecs/mp3dec/src/s_mp3bits.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_mp3bits.h
rename to media/module/codecs/mp3dec/src/s_mp3bits.h
diff --git a/media/codecs/mp3dec/src/s_tmp3dec_chan.h b/media/module/codecs/mp3dec/src/s_tmp3dec_chan.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_tmp3dec_chan.h
rename to media/module/codecs/mp3dec/src/s_tmp3dec_chan.h
diff --git a/media/codecs/mp3dec/src/s_tmp3dec_file.h b/media/module/codecs/mp3dec/src/s_tmp3dec_file.h
similarity index 100%
rename from media/codecs/mp3dec/src/s_tmp3dec_file.h
rename to media/module/codecs/mp3dec/src/s_tmp3dec_file.h
diff --git a/media/codecs/mp3dec/test/Android.bp b/media/module/codecs/mp3dec/test/Android.bp
similarity index 90%
rename from media/codecs/mp3dec/test/Android.bp
rename to media/module/codecs/mp3dec/test/Android.bp
index f10b6ae..dd06bdc 100644
--- a/media/codecs/mp3dec/test/Android.bp
+++ b/media/module/codecs/mp3dec/test/Android.bp
@@ -56,4 +56,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mp3dec/test/Mp3DecoderTest-1.2.zip?unzip=true",
+    ],
 }
diff --git a/media/codecs/mp3dec/test/AndroidTest.xml b/media/module/codecs/mp3dec/test/AndroidTest.xml
similarity index 100%
rename from media/codecs/mp3dec/test/AndroidTest.xml
rename to media/module/codecs/mp3dec/test/AndroidTest.xml
diff --git a/media/codecs/mp3dec/test/Mp3DecoderTest.cpp b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
similarity index 89%
rename from media/codecs/mp3dec/test/Mp3DecoderTest.cpp
rename to media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
index 91326a8..88e9eae 100644
--- a/media/codecs/mp3dec/test/Mp3DecoderTest.cpp
+++ b/media/module/codecs/mp3dec/test/Mp3DecoderTest.cpp
@@ -20,6 +20,7 @@
 #include <utils/Log.h>
 
 #include <audio_utils/sndfile.h>
+#include <memory>
 #include <stdio.h>
 
 #include "mp3reader.h"
@@ -99,27 +100,23 @@
 TEST_F(Mp3DecoderTest, MultiCreateMp3DecoderTest) {
     size_t memRequirements = pvmp3_decoderMemRequirements();
     ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
-    void *decoderBuf = malloc(memRequirements);
+    unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
     for (int count = 0; count < kMaxCount; count++) {
-        pvmp3_InitDecoder(mConfig, decoderBuf);
+        pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
         ALOGV("Decoder created successfully");
     }
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(Mp3DecoderTest, DecodeTest) {
     size_t memRequirements = pvmp3_decoderMemRequirements();
     ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
-    void *decoderBuf = malloc(memRequirements);
+    unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
-    pvmp3_InitDecoder(mConfig, decoderBuf);
+    pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
     ALOGV("Decoder created successfully");
     string inputFile = gEnv->getRes() + GetParam();
     bool status = mMp3Reader.init(inputFile.c_str());
@@ -130,27 +127,23 @@
     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
-    ERROR_CODE decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    ERROR_CODE decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
     ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
     ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
     ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
 
     mMp3Reader.close();
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 TEST_P(Mp3DecoderTest, ResetDecoderTest) {
     size_t memRequirements = pvmp3_decoderMemRequirements();
     ASSERT_NE(memRequirements, 0) << "Failed to get the memory requirement size";
-    void *decoderBuf = malloc(memRequirements);
+    unique_ptr<char[]> decoderBuf(new char[memRequirements]);
     ASSERT_NE(decoderBuf, nullptr)
             << "Failed to allocate decoder memory of size " << memRequirements;
 
-    pvmp3_InitDecoder(mConfig, decoderBuf);
+    pvmp3_InitDecoder(mConfig, (void*)decoderBuf.get());
     ALOGV("Decoder created successfully.");
     string inputFile = gEnv->getRes() + GetParam();
     bool status = mMp3Reader.init(inputFile.c_str());
@@ -162,24 +155,20 @@
     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
 
     ERROR_CODE decoderErr;
-    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo, kNumFrameReset);
+    decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo, kNumFrameReset);
     ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
     ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
     ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
 
-    pvmp3_resetDecoder(decoderBuf);
+    pvmp3_resetDecoder((void*)decoderBuf.get());
     // Decode the same file.
-    decoderErr = DecodeFrames(decoderBuf, outFileHandle, sfInfo);
+    decoderErr = DecodeFrames((void*)decoderBuf.get(), outFileHandle, sfInfo);
     ASSERT_EQ(decoderErr, NO_DECODING_ERROR) << "Failed to decode the frames";
     ASSERT_EQ(sfInfo.channels, mConfig->num_channels) << "Number of channels does not match";
     ASSERT_EQ(sfInfo.samplerate, mConfig->samplingRate) << "Sample rate does not match";
 
     mMp3Reader.close();
     sf_close(outFileHandle);
-    if (decoderBuf) {
-        free(decoderBuf);
-        decoderBuf = nullptr;
-    }
 }
 
 INSTANTIATE_TEST_SUITE_P(Mp3DecoderTestAll, Mp3DecoderTest,
diff --git a/media/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h b/media/module/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
similarity index 100%
rename from media/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
rename to media/module/codecs/mp3dec/test/Mp3DecoderTestEnvironment.h
diff --git a/media/codecs/mp3dec/test/README.md b/media/module/codecs/mp3dec/test/README.md
similarity index 100%
rename from media/codecs/mp3dec/test/README.md
rename to media/module/codecs/mp3dec/test/README.md
diff --git a/media/codecs/mp3dec/test/mp3dec_test.cpp b/media/module/codecs/mp3dec/test/mp3dec_test.cpp
similarity index 100%
rename from media/codecs/mp3dec/test/mp3dec_test.cpp
rename to media/module/codecs/mp3dec/test/mp3dec_test.cpp
diff --git a/media/codecs/mp3dec/test/mp3reader.cpp b/media/module/codecs/mp3dec/test/mp3reader.cpp
similarity index 100%
rename from media/codecs/mp3dec/test/mp3reader.cpp
rename to media/module/codecs/mp3dec/test/mp3reader.cpp
diff --git a/media/codecs/mp3dec/test/mp3reader.h b/media/module/codecs/mp3dec/test/mp3reader.h
similarity index 100%
rename from media/codecs/mp3dec/test/mp3reader.h
rename to media/module/codecs/mp3dec/test/mp3reader.h
diff --git a/services/mediacodec/registrant/Android.bp b/media/module/codecserviceregistrant/Android.bp
similarity index 95%
rename from services/mediacodec/registrant/Android.bp
rename to media/module/codecserviceregistrant/Android.bp
index 12cc32a..5637b37 100644
--- a/services/mediacodec/registrant/Android.bp
+++ b/media/module/codecserviceregistrant/Android.bp
@@ -4,7 +4,6 @@
     // all of the 'license_kinds' from "frameworks_av_services_mediacodec_license"
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_av_services_mediacodec_license"],
 }
 
 cc_library {
diff --git a/services/mediacodec/registrant/CodecServiceRegistrant.cpp b/media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
similarity index 100%
rename from services/mediacodec/registrant/CodecServiceRegistrant.cpp
rename to media/module/codecserviceregistrant/CodecServiceRegistrant.cpp
diff --git a/services/mediacodec/registrant/fuzzer/Android.bp b/media/module/codecserviceregistrant/fuzzer/Android.bp
similarity index 94%
rename from services/mediacodec/registrant/fuzzer/Android.bp
rename to media/module/codecserviceregistrant/fuzzer/Android.bp
index 43afbf1..0b9affd 100644
--- a/services/mediacodec/registrant/fuzzer/Android.bp
+++ b/media/module/codecserviceregistrant/fuzzer/Android.bp
@@ -20,7 +20,6 @@
     // all of the 'license_kinds' from "frameworks_av_services_mediacodec_license"
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["frameworks_av_services_mediacodec_license"],
 }
 
 cc_fuzz {
diff --git a/services/mediacodec/registrant/fuzzer/README.md b/media/module/codecserviceregistrant/fuzzer/README.md
similarity index 100%
rename from services/mediacodec/registrant/fuzzer/README.md
rename to media/module/codecserviceregistrant/fuzzer/README.md
diff --git a/services/mediacodec/registrant/fuzzer/codecServiceRegistrant_fuzzer.cpp b/media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
similarity index 100%
rename from services/mediacodec/registrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
rename to media/module/codecserviceregistrant/fuzzer/codecServiceRegistrant_fuzzer.cpp
diff --git a/media/module/esds/Android.bp b/media/module/esds/Android.bp
new file mode 100644
index 0000000..272d4d7
--- /dev/null
+++ b/media/module/esds/Android.bp
@@ -0,0 +1,44 @@
+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"],
+}
+
+cc_library_static {
+    name: "libstagefright_esds",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+    ],
+    min_sdk_version: "29",
+
+    export_include_dirs: ["include"],
+
+    local_include_dirs: ["include"],
+
+    srcs: ["ESDS.cpp"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    sanitize: {
+        misc_undefined: [
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+    shared_libs: [
+        "libstagefright_foundation",
+        "libutils"
+    ],
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/libstagefright/ESDS.cpp b/media/module/esds/ESDS.cpp
similarity index 99%
rename from media/libstagefright/ESDS.cpp
rename to media/module/esds/ESDS.cpp
index ea059e8..906250b 100644
--- a/media/libstagefright/ESDS.cpp
+++ b/media/module/esds/ESDS.cpp
@@ -20,7 +20,7 @@
 
 #include <media/stagefright/foundation/ByteUtils.h>
 
-#include "include/ESDS.h"
+#include <media/esds/ESDS.h>
 
 #include <string.h>
 
diff --git a/media/module/esds/TEST_MAPPING b/media/module/esds/TEST_MAPPING
new file mode 100644
index 0000000..9368b6d
--- /dev/null
+++ b/media/module/esds/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/esds
+{
+  // tests which require dynamic content
+  // invoke with: atest -- --enable-module-dynamic-download=true
+  // TODO(b/148094059): unit tests not allowed to download content
+  "dynamic-presubmit": [
+    { "name": "ESDSTest" }
+  ]
+}
diff --git a/media/libstagefright/include/ESDS.h b/media/module/esds/include/media/esds/ESDS.h
similarity index 100%
rename from media/libstagefright/include/ESDS.h
rename to media/module/esds/include/media/esds/ESDS.h
diff --git a/media/libstagefright/tests/ESDS/Android.bp b/media/module/esds/tests/Android.bp
similarity index 93%
rename from media/libstagefright/tests/ESDS/Android.bp
rename to media/module/esds/tests/Android.bp
index 04e9b29..aea611e 100644
--- a/media/libstagefright/tests/ESDS/Android.bp
+++ b/media/module/esds/tests/Android.bp
@@ -20,9 +20,6 @@
     // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: [
-        "frameworks_av_media_libstagefright_tests_license",
-    ],
 }
 
 cc_test {
diff --git a/media/libstagefright/tests/ESDS/AndroidTest.xml b/media/module/esds/tests/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/tests/ESDS/AndroidTest.xml
rename to media/module/esds/tests/AndroidTest.xml
diff --git a/media/libstagefright/tests/ESDS/ESDSTest.cpp b/media/module/esds/tests/ESDSTest.cpp
similarity index 96%
rename from media/libstagefright/tests/ESDS/ESDSTest.cpp
rename to media/module/esds/tests/ESDSTest.cpp
index 101e00c..33bdcac 100644
--- a/media/libstagefright/tests/ESDS/ESDSTest.cpp
+++ b/media/module/esds/tests/ESDSTest.cpp
@@ -21,8 +21,9 @@
 #include <stdio.h>
 #include <string.h>
 #include <fstream>
+#include <memory>
 
-#include <ESDS.h>
+#include <media/esds/ESDS.h>
 #include <binder/ProcessState.h>
 #include <datasource/FileSource.h>
 #include <media/stagefright/MediaExtractorFactory.h>
@@ -121,18 +122,16 @@
 };
 
 TEST_P(ESDSUnitTest, InvalidDataTest) {
-    void *invalidData = calloc(mESDSSize, 1);
+    std::unique_ptr<char[]> invalidData(new char[mESDSSize]());
     ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
-    ESDS esds(invalidData, mESDSSize);
-    free(invalidData);
+    ESDS esds((void*)invalidData.get(), mESDSSize);
     ASSERT_NE(esds.InitCheck(), OK) << "invalid ESDS data accepted";
 }
 
 TEST(ESDSSanityUnitTest, ConstructorSanityTest) {
-    void *invalidData = malloc(1);
+    std::unique_ptr<char[]> invalidData(new char[1]());
     ASSERT_NE(invalidData, nullptr) << "Unable to allocate memory";
-    ESDS esds_zero(invalidData, 0);
-    free(invalidData);
+    ESDS esds_zero((void*)invalidData.get(), 0);
     ASSERT_NE(esds_zero.InitCheck(), OK) << "invalid ESDS data accepted";
 
     ESDS esds_null(NULL, 0);
diff --git a/media/libstagefright/tests/ESDS/ESDSTestEnvironment.h b/media/module/esds/tests/ESDSTestEnvironment.h
similarity index 100%
rename from media/libstagefright/tests/ESDS/ESDSTestEnvironment.h
rename to media/module/esds/tests/ESDSTestEnvironment.h
diff --git a/media/libstagefright/tests/ESDS/README.md b/media/module/esds/tests/README.md
similarity index 100%
rename from media/libstagefright/tests/ESDS/README.md
rename to media/module/esds/tests/README.md
diff --git a/media/extractors/Android.bp b/media/module/extractors/Android.bp
similarity index 100%
rename from media/extractors/Android.bp
rename to media/module/extractors/Android.bp
diff --git a/media/extractors/TEST_MAPPING b/media/module/extractors/TEST_MAPPING
similarity index 100%
rename from media/extractors/TEST_MAPPING
rename to media/module/extractors/TEST_MAPPING
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/module/extractors/aac/AACExtractor.cpp
similarity index 98%
rename from media/extractors/aac/AACExtractor.cpp
rename to media/module/extractors/aac/AACExtractor.cpp
index 2fc4584..a44fb61 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/module/extractors/aac/AACExtractor.cpp
@@ -310,9 +310,9 @@
         return AMEDIA_ERROR_END_OF_STREAM;
     }
 
-    MediaBufferHelper *buffer;
+    MediaBufferHelper *buffer = nullptr;
     status_t err = mBufferGroup->acquire_buffer(&buffer);
-    if (err != OK) {
+    if (err != OK || buffer == nullptr) {
         return AMEDIA_ERROR_UNKNOWN;
     }
 
diff --git a/media/extractors/aac/Android.bp b/media/module/extractors/aac/Android.bp
similarity index 100%
rename from media/extractors/aac/Android.bp
rename to media/module/extractors/aac/Android.bp
diff --git a/media/extractors/aac/MODULE_LICENSE_APACHE2 b/media/module/extractors/aac/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/aac/MODULE_LICENSE_APACHE2
rename to media/module/extractors/aac/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/aac/NOTICE b/media/module/extractors/aac/NOTICE
similarity index 100%
rename from media/extractors/aac/NOTICE
rename to media/module/extractors/aac/NOTICE
diff --git a/media/extractors/aac/exports.lds b/media/module/extractors/aac/exports.lds
similarity index 100%
rename from media/extractors/aac/exports.lds
rename to media/module/extractors/aac/exports.lds
diff --git a/media/extractors/aac/include/AACExtractor.h b/media/module/extractors/aac/include/AACExtractor.h
similarity index 100%
rename from media/extractors/aac/include/AACExtractor.h
rename to media/module/extractors/aac/include/AACExtractor.h
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/module/extractors/amr/AMRExtractor.cpp
similarity index 98%
rename from media/extractors/amr/AMRExtractor.cpp
rename to media/module/extractors/amr/AMRExtractor.cpp
index e26ff0a..b0f69ce 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/module/extractors/amr/AMRExtractor.cpp
@@ -341,9 +341,9 @@
         return AMEDIA_ERROR_MALFORMED;
     }
 
-    MediaBufferHelper *buffer;
+    MediaBufferHelper *buffer = nullptr;
     status_t err = mBufferGroup->acquire_buffer(&buffer);
-    if (err != OK) {
+    if (err != OK || buffer == nullptr) {
         return AMEDIA_ERROR_UNKNOWN;
     }
 
diff --git a/media/extractors/amr/Android.bp b/media/module/extractors/amr/Android.bp
similarity index 100%
rename from media/extractors/amr/Android.bp
rename to media/module/extractors/amr/Android.bp
diff --git a/media/extractors/amr/MODULE_LICENSE_APACHE2 b/media/module/extractors/amr/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/amr/MODULE_LICENSE_APACHE2
rename to media/module/extractors/amr/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/amr/NOTICE b/media/module/extractors/amr/NOTICE
similarity index 100%
rename from media/extractors/amr/NOTICE
rename to media/module/extractors/amr/NOTICE
diff --git a/media/extractors/amr/exports.lds b/media/module/extractors/amr/exports.lds
similarity index 100%
rename from media/extractors/amr/exports.lds
rename to media/module/extractors/amr/exports.lds
diff --git a/media/extractors/amr/include/AMRExtractor.h b/media/module/extractors/amr/include/AMRExtractor.h
similarity index 100%
rename from media/extractors/amr/include/AMRExtractor.h
rename to media/module/extractors/amr/include/AMRExtractor.h
diff --git a/media/extractors/flac/Android.bp b/media/module/extractors/flac/Android.bp
similarity index 100%
rename from media/extractors/flac/Android.bp
rename to media/module/extractors/flac/Android.bp
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/module/extractors/flac/FLACExtractor.cpp
similarity index 99%
rename from media/extractors/flac/FLACExtractor.cpp
rename to media/module/extractors/flac/FLACExtractor.cpp
index ec7cb24..2434e41 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/module/extractors/flac/FLACExtractor.cpp
@@ -614,9 +614,9 @@
     }
     // acquire a media buffer
     CHECK(mGroup != NULL);
-    MediaBufferHelper *buffer;
+    MediaBufferHelper *buffer = nullptr;
     status_t err = mGroup->acquire_buffer(&buffer);
-    if (err != OK) {
+    if (err != OK || buffer == nullptr) {
         return NULL;
     }
     const size_t bufferSize = blocksize * getChannels() * getOutputSampleSize();
diff --git a/media/extractors/flac/MODULE_LICENSE_APACHE2 b/media/module/extractors/flac/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/flac/MODULE_LICENSE_APACHE2
rename to media/module/extractors/flac/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/flac/NOTICE b/media/module/extractors/flac/NOTICE
similarity index 100%
rename from media/extractors/flac/NOTICE
rename to media/module/extractors/flac/NOTICE
diff --git a/media/extractors/flac/exports.lds b/media/module/extractors/flac/exports.lds
similarity index 100%
rename from media/extractors/flac/exports.lds
rename to media/module/extractors/flac/exports.lds
diff --git a/media/extractors/flac/include/FLACExtractor.h b/media/module/extractors/flac/include/FLACExtractor.h
similarity index 100%
rename from media/extractors/flac/include/FLACExtractor.h
rename to media/module/extractors/flac/include/FLACExtractor.h
diff --git a/media/extractors/fuzzers/Android.bp b/media/module/extractors/fuzzers/Android.bp
similarity index 99%
rename from media/extractors/fuzzers/Android.bp
rename to media/module/extractors/fuzzers/Android.bp
index 490e195..b3e34d2 100644
--- a/media/extractors/fuzzers/Android.bp
+++ b/media/module/extractors/fuzzers/Android.bp
@@ -173,7 +173,7 @@
     ],
 
     static_libs: [
-        "libwebm",
+        "libwebm_mkvparser",
         "libstagefright_flacdec",
         "libstagefright_metadatautils",
         "libmkvextractor",
diff --git a/media/extractors/fuzzers/ExtractorFuzzerBase.cpp b/media/module/extractors/fuzzers/ExtractorFuzzerBase.cpp
similarity index 100%
rename from media/extractors/fuzzers/ExtractorFuzzerBase.cpp
rename to media/module/extractors/fuzzers/ExtractorFuzzerBase.cpp
diff --git a/media/extractors/fuzzers/README.md b/media/module/extractors/fuzzers/README.md
similarity index 100%
rename from media/extractors/fuzzers/README.md
rename to media/module/extractors/fuzzers/README.md
diff --git a/media/extractors/fuzzers/aac_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/aac_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/aac_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/aac_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/amr_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/amr_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/amr_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/amr_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/amr_extractor_fuzzer.dict b/media/module/extractors/fuzzers/amr_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/amr_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/amr_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/flac_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/flac_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/flac_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/flac_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/flac_extractor_fuzzer.dict b/media/module/extractors/fuzzers/flac_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/flac_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/flac_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/include/ExtractorFuzzerBase.h b/media/module/extractors/fuzzers/include/ExtractorFuzzerBase.h
similarity index 100%
rename from media/extractors/fuzzers/include/ExtractorFuzzerBase.h
rename to media/module/extractors/fuzzers/include/ExtractorFuzzerBase.h
diff --git a/media/extractors/fuzzers/midi_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/midi_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/midi_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/midi_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/midi_extractor_fuzzer.dict b/media/module/extractors/fuzzers/midi_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/midi_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/midi_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mkv_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mkv_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mkv_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mkv_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mkv_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mkv_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mkv_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mkv_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mp3_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mp3_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mp3_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mp3_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mp4_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mp4_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mp4_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mp4_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mp4_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mp4_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/mpeg2_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mpeg2ps_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict b/media/module/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/mpeg2ts_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/ogg_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/ogg_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/ogg_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/ogg_extractor_fuzzer.cpp
diff --git a/media/extractors/fuzzers/ogg_extractor_fuzzer.dict b/media/module/extractors/fuzzers/ogg_extractor_fuzzer.dict
similarity index 100%
rename from media/extractors/fuzzers/ogg_extractor_fuzzer.dict
rename to media/module/extractors/fuzzers/ogg_extractor_fuzzer.dict
diff --git a/media/extractors/fuzzers/wav_extractor_fuzzer.cpp b/media/module/extractors/fuzzers/wav_extractor_fuzzer.cpp
similarity index 100%
rename from media/extractors/fuzzers/wav_extractor_fuzzer.cpp
rename to media/module/extractors/fuzzers/wav_extractor_fuzzer.cpp
diff --git a/media/extractors/midi/Android.bp b/media/module/extractors/midi/Android.bp
similarity index 100%
rename from media/extractors/midi/Android.bp
rename to media/module/extractors/midi/Android.bp
diff --git a/media/extractors/midi/MODULE_LICENSE_APACHE2 b/media/module/extractors/midi/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/midi/MODULE_LICENSE_APACHE2
rename to media/module/extractors/midi/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/module/extractors/midi/MidiExtractor.cpp
similarity index 98%
rename from media/extractors/midi/MidiExtractor.cpp
rename to media/module/extractors/midi/MidiExtractor.cpp
index d0efb2f..167cc40 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/module/extractors/midi/MidiExtractor.cpp
@@ -240,9 +240,9 @@
     if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) {
         return NULL;
     }
-    MediaBufferHelper *buffer;
+    MediaBufferHelper *buffer = nullptr;
     status_t err = mGroup->acquire_buffer(&buffer);
-    if (err != OK) {
+    if (err != OK || buffer == nullptr) {
         ALOGE("readBuffer: no buffer");
         return NULL;
     }
diff --git a/media/extractors/midi/NOTICE b/media/module/extractors/midi/NOTICE
similarity index 100%
rename from media/extractors/midi/NOTICE
rename to media/module/extractors/midi/NOTICE
diff --git a/media/extractors/midi/exports.lds b/media/module/extractors/midi/exports.lds
similarity index 100%
rename from media/extractors/midi/exports.lds
rename to media/module/extractors/midi/exports.lds
diff --git a/media/extractors/midi/include/MidiExtractor.h b/media/module/extractors/midi/include/MidiExtractor.h
similarity index 100%
rename from media/extractors/midi/include/MidiExtractor.h
rename to media/module/extractors/midi/include/MidiExtractor.h
diff --git a/media/extractors/mkv/Android.bp b/media/module/extractors/mkv/Android.bp
similarity index 96%
rename from media/extractors/mkv/Android.bp
rename to media/module/extractors/mkv/Android.bp
index 98ce305..c4b67eb 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/module/extractors/mkv/Android.bp
@@ -33,7 +33,7 @@
         "libstagefright_foundation_colorutils_ndk",   // for mainline-safe ColorUtils
         "libstagefright_foundation",
         "libstagefright_metadatautils",
-        "libwebm",
+        "libwebm_mkvparser",
         "libutils",
     ],
 
diff --git a/media/extractors/mkv/MODULE_LICENSE_APACHE2 b/media/module/extractors/mkv/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/mkv/MODULE_LICENSE_APACHE2
rename to media/module/extractors/mkv/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/module/extractors/mkv/MatroskaExtractor.cpp
similarity index 99%
rename from media/extractors/mkv/MatroskaExtractor.cpp
rename to media/module/extractors/mkv/MatroskaExtractor.cpp
index 443e26c..2b72387 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/module/extractors/mkv/MatroskaExtractor.cpp
@@ -790,6 +790,7 @@
     int64_t timeUs = mBlockIter.blockTimeUs();
 
     for (int i = 0; i < block->GetFrameCount(); ++i) {
+        status_t err;
         MatroskaExtractor::TrackInfo *trackInfo = &mExtractor->mTracks.editItemAt(mTrackIndex);
         const mkvparser::Block::Frame &frame = block->GetFrame(i);
         size_t len = frame.len;
@@ -798,8 +799,13 @@
         }
 
         len += trackInfo->mHeaderLen;
-        MediaBufferHelper *mbuf;
-        mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */, len /* requested size */);
+        MediaBufferHelper *mbuf = nullptr;
+        err = mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */,
+                                           len /* requested size */);
+        if (err != OK || mbuf == nullptr) {
+            ALOGE("readBlock: no buffer");
+            return AMEDIA_ERROR_UNKNOWN;
+        }
         mbuf->set_range(0, len);
         uint8_t *data = static_cast<uint8_t *>(mbuf->data());
         if (trackInfo->mHeader) {
@@ -832,7 +838,7 @@
             }
         }
 
-        status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
+        err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
         if (err == OK
                 && mExtractor->mIsWebm
                 && trackInfo->mEncrypted) {
diff --git a/media/extractors/mkv/NOTICE b/media/module/extractors/mkv/NOTICE
similarity index 100%
rename from media/extractors/mkv/NOTICE
rename to media/module/extractors/mkv/NOTICE
diff --git a/media/extractors/mkv/exports.lds b/media/module/extractors/mkv/exports.lds
similarity index 100%
rename from media/extractors/mkv/exports.lds
rename to media/module/extractors/mkv/exports.lds
diff --git a/media/extractors/mkv/include/MatroskaExtractor.h b/media/module/extractors/mkv/include/MatroskaExtractor.h
similarity index 100%
rename from media/extractors/mkv/include/MatroskaExtractor.h
rename to media/module/extractors/mkv/include/MatroskaExtractor.h
diff --git a/media/extractors/mp3/Android.bp b/media/module/extractors/mp3/Android.bp
similarity index 100%
rename from media/extractors/mp3/Android.bp
rename to media/module/extractors/mp3/Android.bp
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/module/extractors/mp3/MP3Extractor.cpp
similarity index 99%
rename from media/extractors/mp3/MP3Extractor.cpp
rename to media/module/extractors/mp3/MP3Extractor.cpp
index 248a39c..328b790 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/module/extractors/mp3/MP3Extractor.cpp
@@ -521,9 +521,9 @@
         mSamplesRead = 0;
     }
 
-    MediaBufferHelper *buffer;
+    MediaBufferHelper *buffer = nullptr;
     status_t err = mBufferGroup->acquire_buffer(&buffer);
-    if (err != OK) {
+    if (err != OK || buffer == nullptr) {
         return AMEDIA_ERROR_UNKNOWN;
     }
 
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/module/extractors/mp3/VBRISeeker.cpp
similarity index 100%
rename from media/extractors/mp3/VBRISeeker.cpp
rename to media/module/extractors/mp3/VBRISeeker.cpp
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/module/extractors/mp3/XINGSeeker.cpp
similarity index 100%
rename from media/extractors/mp3/XINGSeeker.cpp
rename to media/module/extractors/mp3/XINGSeeker.cpp
diff --git a/media/extractors/mp3/exports.lds b/media/module/extractors/mp3/exports.lds
similarity index 100%
rename from media/extractors/mp3/exports.lds
rename to media/module/extractors/mp3/exports.lds
diff --git a/media/extractors/mp3/include/MP3Extractor.h b/media/module/extractors/mp3/include/MP3Extractor.h
similarity index 100%
rename from media/extractors/mp3/include/MP3Extractor.h
rename to media/module/extractors/mp3/include/MP3Extractor.h
diff --git a/media/extractors/mp3/include/MP3Seeker.h b/media/module/extractors/mp3/include/MP3Seeker.h
similarity index 100%
rename from media/extractors/mp3/include/MP3Seeker.h
rename to media/module/extractors/mp3/include/MP3Seeker.h
diff --git a/media/extractors/mp3/include/VBRISeeker.h b/media/module/extractors/mp3/include/VBRISeeker.h
similarity index 100%
rename from media/extractors/mp3/include/VBRISeeker.h
rename to media/module/extractors/mp3/include/VBRISeeker.h
diff --git a/media/extractors/mp3/include/XINGSeeker.h b/media/module/extractors/mp3/include/XINGSeeker.h
similarity index 100%
rename from media/extractors/mp3/include/XINGSeeker.h
rename to media/module/extractors/mp3/include/XINGSeeker.h
diff --git a/media/extractors/mp4/AC4Parser.cpp b/media/module/extractors/mp4/AC4Parser.cpp
similarity index 100%
rename from media/extractors/mp4/AC4Parser.cpp
rename to media/module/extractors/mp4/AC4Parser.cpp
diff --git a/media/extractors/mp4/Android.bp b/media/module/extractors/mp4/Android.bp
similarity index 100%
rename from media/extractors/mp4/Android.bp
rename to media/module/extractors/mp4/Android.bp
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/module/extractors/mp4/ItemTable.cpp
similarity index 100%
rename from media/extractors/mp4/ItemTable.cpp
rename to media/module/extractors/mp4/ItemTable.cpp
diff --git a/media/extractors/mp4/MODULE_LICENSE_APACHE2 b/media/module/extractors/mp4/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/mp4/MODULE_LICENSE_APACHE2
rename to media/module/extractors/mp4/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
similarity index 99%
rename from media/extractors/mp4/MPEG4Extractor.cpp
rename to media/module/extractors/mp4/MPEG4Extractor.cpp
index fb9dfb4..1d88785 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -34,7 +34,7 @@
 #include "SampleTable.h"
 #include "ItemTable.h"
 
-#include <ESDS.h>
+#include <media/esds/ESDS.h>
 #include <ID3.h>
 #include <media/stagefright/DataSourceBase.h>
 #include <media/ExtractorUtils.h>
@@ -394,6 +394,15 @@
             return MEDIA_MIMETYPE_AUDIO_MPEGH_MHA1;
         case FOURCC("mhm1"):
             return MEDIA_MIMETYPE_AUDIO_MPEGH_MHM1;
+        case FOURCC("dtsc"):
+            return MEDIA_MIMETYPE_AUDIO_DTS;
+        case FOURCC("dtse"):
+        case FOURCC("dtsh"):
+            return MEDIA_MIMETYPE_AUDIO_DTS_HD;
+        case FOURCC("dtsl"):
+            return MEDIA_MIMETYPE_AUDIO_DTS_HD_MA;
+        case FOURCC("dtsx"):
+            return MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2;
         default:
             ALOGW("Unknown fourcc: %c%c%c%c",
                    (fourcc >> 24) & 0xff,
@@ -1804,6 +1813,11 @@
         case 0x6D730055: // "ms U" mp3 audio
         case FOURCC("mha1"):
         case FOURCC("mhm1"):
+        case FOURCC("dtsc"):
+        case FOURCC("dtse"):
+        case FOURCC("dtsh"):
+        case FOURCC("dtsl"):
+        case FOURCC("dtsx"):
         {
             if (mIsQT && depth >= 1 && mPath[depth - 1] == FOURCC("wave")) {
 
@@ -1969,26 +1983,8 @@
             }
 
             if (chunk_type == FOURCC("fLaC")) {
-
-                // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt
-                // 4 for mime, 4 for blockType and BlockLen, 34 for metadata
-                uint8_t flacInfo[4 + 4 + 34];
-                // skipping dFla, version
-                data_offset += sizeof(buffer) + 12;
-                size_t flacOffset = 4;
-                // Add flaC header mime type to CSD
-                strncpy((char *)flacInfo, "fLaC", 4);
-                if (mDataSource->readAt(
-                        data_offset, flacInfo + flacOffset, sizeof(flacInfo) - flacOffset) <
-                        (ssize_t)sizeof(flacInfo) - flacOffset) {
-                    return ERROR_IO;
-                }
-                data_offset += sizeof(flacInfo) - flacOffset;
-
-                AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo,
-                                       sizeof(flacInfo));
+                data_offset += sizeof(buffer);
                 *offset = data_offset;
-                CHECK_EQ(*offset, stop_offset);
             }
 
             while (*offset < stop_offset) {
@@ -2521,6 +2517,35 @@
             break;
         }
 
+        case FOURCC("dfLa"):
+        {
+            *offset += chunk_size;
+
+            // From https://github.com/xiph/flac/blob/master/doc/isoflac.txt
+            // 4 for mediaType, 4 for blockType and BlockLen, 34 for metadata
+            uint8_t flacInfo[4 + 4 + 34];
+
+            if (chunk_data_size != sizeof(flacInfo)) {
+                return ERROR_MALFORMED;
+            }
+
+            data_offset += 4;
+            size_t flacOffset = 4;
+            // Add flaC header mediaType to CSD
+            strncpy((char *)flacInfo, "fLaC", 4);
+
+            ssize_t bytesToRead = sizeof(flacInfo) - flacOffset;
+            if (mDataSource->readAt(
+                    data_offset, flacInfo + flacOffset, bytesToRead) < bytesToRead) {
+                return ERROR_IO;
+            }
+
+            data_offset += bytesToRead;
+            AMediaFormat_setBuffer(mLastTrack->meta, AMEDIAFORMAT_KEY_CSD_0, flacInfo,
+                                    sizeof(flacInfo));
+            break;
+        }
+
         case FOURCC("avcC"):
         {
             *offset += chunk_size;
@@ -6312,7 +6337,7 @@
 
         err = mBufferGroup->acquire_buffer(&mBuffer);
 
-        if (err != OK) {
+        if (err != OK || mBuffer == nullptr) {
             CHECK(mBuffer == NULL);
             return AMEDIA_ERROR_UNKNOWN;
         }
@@ -6712,7 +6737,7 @@
         const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
         offset = smpl->offset;
         size = smpl->size;
-        cts = mCurrentTime + smpl->compositionOffset;
+        cts = (int64_t)mCurrentTime + (int64_t)smpl->compositionOffset;
 
         if (mElstInitialEmptyEditTicks > 0) {
             cts += mElstInitialEmptyEditTicks;
diff --git a/media/extractors/mp4/NOTICE b/media/module/extractors/mp4/NOTICE
similarity index 100%
rename from media/extractors/mp4/NOTICE
rename to media/module/extractors/mp4/NOTICE
diff --git a/media/extractors/mp4/SampleIterator.cpp b/media/module/extractors/mp4/SampleIterator.cpp
similarity index 100%
rename from media/extractors/mp4/SampleIterator.cpp
rename to media/module/extractors/mp4/SampleIterator.cpp
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/module/extractors/mp4/SampleTable.cpp
similarity index 100%
rename from media/extractors/mp4/SampleTable.cpp
rename to media/module/extractors/mp4/SampleTable.cpp
diff --git a/media/extractors/mp4/exports.lds b/media/module/extractors/mp4/exports.lds
similarity index 100%
rename from media/extractors/mp4/exports.lds
rename to media/module/extractors/mp4/exports.lds
diff --git a/media/extractors/mp4/include/AC4Parser.h b/media/module/extractors/mp4/include/AC4Parser.h
similarity index 100%
rename from media/extractors/mp4/include/AC4Parser.h
rename to media/module/extractors/mp4/include/AC4Parser.h
diff --git a/media/extractors/mp4/include/ItemTable.h b/media/module/extractors/mp4/include/ItemTable.h
similarity index 100%
rename from media/extractors/mp4/include/ItemTable.h
rename to media/module/extractors/mp4/include/ItemTable.h
diff --git a/media/extractors/mp4/include/MPEG4Extractor.h b/media/module/extractors/mp4/include/MPEG4Extractor.h
similarity index 100%
rename from media/extractors/mp4/include/MPEG4Extractor.h
rename to media/module/extractors/mp4/include/MPEG4Extractor.h
diff --git a/media/extractors/mp4/include/SampleIterator.h b/media/module/extractors/mp4/include/SampleIterator.h
similarity index 100%
rename from media/extractors/mp4/include/SampleIterator.h
rename to media/module/extractors/mp4/include/SampleIterator.h
diff --git a/media/extractors/mp4/include/SampleTable.h b/media/module/extractors/mp4/include/SampleTable.h
similarity index 100%
rename from media/extractors/mp4/include/SampleTable.h
rename to media/module/extractors/mp4/include/SampleTable.h
diff --git a/media/extractors/mpeg2/Android.bp b/media/module/extractors/mpeg2/Android.bp
similarity index 100%
rename from media/extractors/mpeg2/Android.bp
rename to media/module/extractors/mpeg2/Android.bp
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/module/extractors/mpeg2/ExtractorBundle.cpp
similarity index 100%
rename from media/extractors/mpeg2/ExtractorBundle.cpp
rename to media/module/extractors/mpeg2/ExtractorBundle.cpp
diff --git a/media/extractors/mpeg2/MODULE_LICENSE_APACHE2 b/media/module/extractors/mpeg2/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/mpeg2/MODULE_LICENSE_APACHE2
rename to media/module/extractors/mpeg2/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/module/extractors/mpeg2/MPEG2PSExtractor.cpp
similarity index 97%
rename from media/extractors/mpeg2/MPEG2PSExtractor.cpp
rename to media/module/extractors/mpeg2/MPEG2PSExtractor.cpp
index afd28ef..44c8937 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/module/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -699,11 +699,26 @@
         }
     }
 
-    MediaBufferBase *mbuf;
-    mSource->read(&mbuf, (MediaTrack::ReadOptions*) options);
+    MediaBufferBase *mbuf = nullptr;
+    status_t err_read = mSource->read(&mbuf, (MediaTrack::ReadOptions*) options);
+    if (mbuf == nullptr) {
+        ALOGE("Track::read: null buffer read from source");
+        return AMEDIA_ERROR_UNKNOWN;
+    }
+    if (err_read != OK) {
+        ALOGE("Track::read: no buffer read from source");
+        mbuf->release();
+        return AMEDIA_ERROR_UNKNOWN;
+    }
+
     size_t length = mbuf->range_length();
-    MediaBufferHelper *outbuf;
-    mBufferGroup->acquire_buffer(&outbuf, false, length);
+    MediaBufferHelper *outbuf = nullptr;
+    status_t err = mBufferGroup->acquire_buffer(&outbuf, false, length);
+    if (err != OK || outbuf == nullptr) {
+        ALOGE("Track::read: no buffer");
+        mbuf->release();
+        return AMEDIA_ERROR_UNKNOWN;
+    }
     memcpy(outbuf->data(), mbuf->data(), length);
     outbuf->set_range(0, length);
     *buffer = outbuf;
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/module/extractors/mpeg2/MPEG2TSExtractor.cpp
similarity index 97%
rename from media/extractors/mpeg2/MPEG2TSExtractor.cpp
rename to media/module/extractors/mpeg2/MPEG2TSExtractor.cpp
index 9a3cd92..736b817 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/module/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -182,11 +182,26 @@
         return AMEDIA_ERROR_END_OF_STREAM;
     }
 
-    MediaBufferBase *mbuf;
-    mImpl->read(&mbuf, (MediaTrack::ReadOptions*) options);
+    MediaBufferBase *mbuf = nullptr;
+    status_t err_read = mImpl->read(&mbuf, (MediaTrack::ReadOptions*) options);
+    if (mbuf == nullptr) {
+        ALOGE("Track::read: null buffer read from source");
+        return AMEDIA_ERROR_UNKNOWN;
+    }
+    if (err_read != OK) {
+        ALOGE("Track::read: no buffer read from source");
+        mbuf->release();
+        return AMEDIA_ERROR_UNKNOWN;
+    }
+
     size_t length = mbuf->range_length();
-    MediaBufferHelper *outbuf;
-    mBufferGroup->acquire_buffer(&outbuf, false, length);
+    MediaBufferHelper *outbuf = nullptr;
+    status_t err = mBufferGroup->acquire_buffer(&outbuf, false, length);
+    if (err != OK || outbuf == nullptr) {
+        ALOGE("read: no buffer");
+        mbuf->release();
+        return AMEDIA_ERROR_UNKNOWN;
+    }
     memcpy(outbuf->data(), mbuf->data(), length);
     outbuf->set_range(0, length);
     *out = outbuf;
diff --git a/media/extractors/mpeg2/NOTICE b/media/module/extractors/mpeg2/NOTICE
similarity index 100%
rename from media/extractors/mpeg2/NOTICE
rename to media/module/extractors/mpeg2/NOTICE
diff --git a/media/extractors/mpeg2/exports.lds b/media/module/extractors/mpeg2/exports.lds
similarity index 100%
rename from media/extractors/mpeg2/exports.lds
rename to media/module/extractors/mpeg2/exports.lds
diff --git a/media/extractors/mpeg2/include/MPEG2PSExtractor.h b/media/module/extractors/mpeg2/include/MPEG2PSExtractor.h
similarity index 100%
rename from media/extractors/mpeg2/include/MPEG2PSExtractor.h
rename to media/module/extractors/mpeg2/include/MPEG2PSExtractor.h
diff --git a/media/extractors/mpeg2/include/MPEG2TSExtractor.h b/media/module/extractors/mpeg2/include/MPEG2TSExtractor.h
similarity index 100%
rename from media/extractors/mpeg2/include/MPEG2TSExtractor.h
rename to media/module/extractors/mpeg2/include/MPEG2TSExtractor.h
diff --git a/media/extractors/ogg/Android.bp b/media/module/extractors/ogg/Android.bp
similarity index 100%
rename from media/extractors/ogg/Android.bp
rename to media/module/extractors/ogg/Android.bp
diff --git a/media/extractors/ogg/MODULE_LICENSE_APACHE2 b/media/module/extractors/ogg/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/ogg/MODULE_LICENSE_APACHE2
rename to media/module/extractors/ogg/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/ogg/NOTICE b/media/module/extractors/ogg/NOTICE
similarity index 100%
rename from media/extractors/ogg/NOTICE
rename to media/module/extractors/ogg/NOTICE
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/module/extractors/ogg/OggExtractor.cpp
similarity index 90%
rename from media/extractors/ogg/OggExtractor.cpp
rename to media/module/extractors/ogg/OggExtractor.cpp
index eb2246d..4c106b2 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/module/extractors/ogg/OggExtractor.cpp
@@ -34,6 +34,9 @@
 #include <system/audio.h>
 #include <utils/String8.h>
 
+#include <inttypes.h>
+#include <stdint.h>
+
 extern "C" {
     #include <Tremolo/codec_internal.h>
 
@@ -346,66 +349,118 @@
         off64_t startOffset, off64_t *pageOffset) {
     *pageOffset = startOffset;
 
-    for (;;) {
-        char signature[4];
-        ssize_t n = mSource->readAt(*pageOffset, &signature, 4);
+    // balance between larger reads and reducing how much we over-read.
+    const int FIND_BUF_SIZE = 2048;
+    const int lenOggS = strlen("OggS");
+    while(1) {
 
-        if (n < 4) {
+        // work with big buffers to amortize readAt() costs
+        char signatureBuffer[FIND_BUF_SIZE];
+        ssize_t n = mSource->readAt(*pageOffset, &signatureBuffer, sizeof(signatureBuffer));
+
+        if (n < lenOggS) {
             *pageOffset = 0;
-
             return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM;
         }
 
-        if (!memcmp(signature, "OggS", 4)) {
-            if (*pageOffset > startOffset) {
-                ALOGV("skipped %lld bytes of junk to reach next frame",
-                     (long long)(*pageOffset - startOffset));
-            }
-
-            return OK;
-        }
-
-        // see how far ahead to skip; avoid some fruitless comparisons
-        unsigned int i;
-        for (i = 1; i < 4 ; i++) {
-            if (signature[i] == 'O')
+        for(int i = 0; i < n - (lenOggS - 1) ; i++) {
+            // fast scan for 1st character in a signature
+            char *p = (char *)memchr(&signatureBuffer[i], 'O', n - (lenOggS - 1) - i);
+            if (p == NULL) {
+                // no signature start in the rest of this buffer.
                 break;
+            }
+            int jump = (p-&signatureBuffer[i]);
+            i += jump;
+            if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+                *pageOffset += i;
+                if (*pageOffset > startOffset) {
+                    ALOGD("skipped %" PRIu64 " bytes of junk to reach next frame",
+                         (*pageOffset - startOffset));
+                }
+                return OK;
+            }
         }
-        *pageOffset += i;
+
+        // on to next block. buffer didn't end with "OggS", but could end with "Ogg".
+        // overlap enough to detect this. n >= lenOggS, so this always advances.
+        *pageOffset += n - (lenOggS - 1);
     }
+    return (status_t)ERROR_END_OF_STREAM;
 }
 
 // Given the offset of the "current" page, find the page immediately preceding
 // it (if any) and return its granule position.
 // To do this we back up from the "current" page's offset until we find any
 // page preceding it and then scan forward to just before the current page.
+//
 status_t MyOggExtractor::findPrevGranulePosition(
         off64_t pageOffset, uint64_t *granulePos) {
     *granulePos = 0;
 
-    off64_t prevPageOffset = 0;
-    off64_t prevGuess = pageOffset;
-    for (;;) {
-        if (prevGuess >= 5000) {
-            prevGuess -= 5000;
+    const int FIND_BUF_SIZE = 2048;
+    const int lenOggS = strlen("OggS");
+
+    if (pageOffset == 0) {
+        ALOGV("no page before the first page");
+        return UNKNOWN_ERROR;
+    }
+
+    off64_t prevPageOffset = pageOffset;
+
+    // we start our search on the byte immediately in front of pageOffset
+    // which could mean "O" immediately before and "ggS" starting at pageOffset
+    //
+    // if there was an "OggS" at pageOffset, we'll have scanned a few extra bytes
+    // but if pageOffset was chosen by a seek operation, we don't know that it
+    // reflects the beginning of a page. By choosing to scan 3 possibly unneeded
+    // bytes at the start we cover both cases.
+    //
+    off64_t firstAfter = pageOffset + lenOggS - 1;    // NOT within our buffer
+    off64_t nextOffset = pageOffset;
+
+    while(prevPageOffset == pageOffset) {
+        // work with big buffers to amortize readAt() costs
+        char signatureBuffer[FIND_BUF_SIZE];
+
+        ssize_t desired = sizeof(signatureBuffer);
+        if (firstAfter >= desired) {
+            nextOffset = firstAfter - desired;
         } else {
-            prevGuess = 0;
+            nextOffset = 0;
+            desired = firstAfter;
         }
+        ssize_t n = mSource->readAt(nextOffset, &signatureBuffer, desired);
 
-        ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess));
-
-        status_t err = findNextPage(prevGuess, &prevPageOffset);
-        if (err == ERROR_END_OF_STREAM) {
-            // We are at the last page and didn't back off enough;
-            // back off 5000 bytes more and try again.
-            continue;
-        } else if (err != OK) {
-            return err;
-        }
-
-        if (prevPageOffset < pageOffset || prevGuess == 0) {
+        if (n < lenOggS) {
+            ALOGD("short read, get out");
             break;
         }
+
+        // work backwards
+        // loop control ok for n >= 0
+        for(int i = n - lenOggS; i >= 0 ; i--) {
+            // fast scan for 1st character in the signature
+            char *p = (char *)memrchr(&signatureBuffer[0], 'O', i);
+            if (p == NULL) {
+                // no signature start in the rest of this buffer.
+                break;
+            }
+            i = (p-&signatureBuffer[0]);
+            // loop start chosen to ensure we will always have lenOggS bytes
+            if (memcmp("OggS", &signatureBuffer[i], lenOggS) == 0) {
+                prevPageOffset = nextOffset + i;
+                break;
+            }
+        }
+
+        // back up for next read; make sure we catch overlaps
+        if (nextOffset == 0) {
+            // can't back up any further
+            break;
+        }
+        // current buffer might start with "ggS", include those bytes in the next iteration
+        firstAfter = nextOffset + lenOggS - 1;
     }
 
     if (prevPageOffset == pageOffset) {
@@ -413,8 +468,8 @@
         return UNKNOWN_ERROR;
     }
 
-    ALOGV("prevPageOffset at %lld, pageOffset at %lld",
-            (long long)prevPageOffset, (long long)pageOffset);
+    ALOGV("prevPageOffset at %" PRIu64 ", pageOffset at %" PRIu64,
+          prevPageOffset, pageOffset);
     uint8_t flag = 0;
     for (;;) {
         Page prevPage;
@@ -790,7 +845,8 @@
             }
             MediaBufferHelper *tmp;
             if (mBufferGroup) {
-                mBufferGroup->acquire_buffer(&tmp, false, fullSize);
+                // ignore return code here. instead, check tmp below.
+                (void) mBufferGroup->acquire_buffer(&tmp, false, fullSize);
                 ALOGV("acquired buffer %p from group", tmp);
             } else {
                 tmp = new StandAloneMediaBuffer(fullSize);
@@ -924,13 +980,16 @@
 status_t MyOggExtractor::init() {
     AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType);
 
-    media_status_t err;
-    MediaBufferHelper *packet;
     for (size_t i = 0; i < mNumHeaders; ++i) {
+        media_status_t err;
+        MediaBufferHelper *packet = nullptr;
         // ignore timestamp for configuration packets
         if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) {
             return err;
         }
+        if (packet == nullptr) {
+            return AMEDIA_ERROR_UNKNOWN;
+        }
         ALOGV("read packet of size %zu\n", packet->range_length());
         err = verifyHeader(packet, /* type = */ i * 2 + 1);
         packet->release();
@@ -989,16 +1048,21 @@
     size_t numerator = mTableOfContents.size();
 
     if (numerator > kMaxNumTOCEntries) {
-        size_t denom = numerator - kMaxNumTOCEntries;
+        Vector<TOCEntry> maxTOC;
+        maxTOC.setCapacity(kMaxNumTOCEntries);
 
+        size_t denom = numerator - kMaxNumTOCEntries;
         size_t accum = 0;
-        for (ssize_t i = mTableOfContents.size(); i > 0; --i) {
+        for (ssize_t i = 0; i < mTableOfContents.size(); i++) {
             accum += denom;
             if (accum >= numerator) {
-                mTableOfContents.removeAt(i);
                 accum -= numerator;
+            } else {
+                maxTOC.push(mTableOfContents.itemAt(i));
             }
         }
+
+        mTableOfContents = maxTOC;
     }
 }
 
diff --git a/media/extractors/ogg/exports.lds b/media/module/extractors/ogg/exports.lds
similarity index 100%
rename from media/extractors/ogg/exports.lds
rename to media/module/extractors/ogg/exports.lds
diff --git a/media/extractors/ogg/include/OggExtractor.h b/media/module/extractors/ogg/include/OggExtractor.h
similarity index 100%
rename from media/extractors/ogg/include/OggExtractor.h
rename to media/module/extractors/ogg/include/OggExtractor.h
diff --git a/media/extractors/tests/Android.bp b/media/module/extractors/tests/Android.bp
similarity index 93%
rename from media/extractors/tests/Android.bp
rename to media/module/extractors/tests/Android.bp
index 3c3bbdc..f5eadbd 100644
--- a/media/extractors/tests/Android.bp
+++ b/media/module/extractors/tests/Android.bp
@@ -55,7 +55,7 @@
         "libmedia_midiiowrapper",
         "libsonivoxwithoutjet",
         "libvorbisidec",
-        "libwebm",
+        "libwebm_mkvparser",
         "libFLAC",
     ],
 
@@ -100,4 +100,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/extractors/tests/extractor-1.4.zip?unzip=true",
+    ],
 }
diff --git a/media/extractors/tests/AndroidTest.xml b/media/module/extractors/tests/AndroidTest.xml
similarity index 100%
rename from media/extractors/tests/AndroidTest.xml
rename to media/module/extractors/tests/AndroidTest.xml
diff --git a/media/extractors/tests/ExtractorUnitTest.cpp b/media/module/extractors/tests/ExtractorUnitTest.cpp
similarity index 100%
rename from media/extractors/tests/ExtractorUnitTest.cpp
rename to media/module/extractors/tests/ExtractorUnitTest.cpp
diff --git a/media/extractors/tests/ExtractorUnitTestEnvironment.h b/media/module/extractors/tests/ExtractorUnitTestEnvironment.h
similarity index 100%
rename from media/extractors/tests/ExtractorUnitTestEnvironment.h
rename to media/module/extractors/tests/ExtractorUnitTestEnvironment.h
diff --git a/media/extractors/tests/README.md b/media/module/extractors/tests/README.md
similarity index 100%
rename from media/extractors/tests/README.md
rename to media/module/extractors/tests/README.md
diff --git a/media/extractors/wav/Android.bp b/media/module/extractors/wav/Android.bp
similarity index 100%
rename from media/extractors/wav/Android.bp
rename to media/module/extractors/wav/Android.bp
diff --git a/media/extractors/wav/MODULE_LICENSE_APACHE2 b/media/module/extractors/wav/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/extractors/wav/MODULE_LICENSE_APACHE2
rename to media/module/extractors/wav/MODULE_LICENSE_APACHE2
diff --git a/media/extractors/wav/NOTICE b/media/module/extractors/wav/NOTICE
similarity index 100%
rename from media/extractors/wav/NOTICE
rename to media/module/extractors/wav/NOTICE
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/module/extractors/wav/WAVExtractor.cpp
similarity index 98%
rename from media/extractors/wav/WAVExtractor.cpp
rename to media/module/extractors/wav/WAVExtractor.cpp
index 9e94587..9c3bac6 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/module/extractors/wav/WAVExtractor.cpp
@@ -459,11 +459,15 @@
         mCurrentPos = pos + mOffset;
     }
 
-    MediaBufferHelper *buffer;
+    MediaBufferHelper *buffer = nullptr;
     media_status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return err;
     }
+    if (buffer == nullptr) {
+        ALOGE("acquire_buffer OK, but no buffer");
+        return AMEDIA_ERROR_UNKNOWN;
+    }
 
     // maxBytesToRead may be reduced so that in-place data conversion will fit in buffer size.
     const size_t bufferSize = std::min(buffer->size(), kMaxFrameSize);
diff --git a/media/extractors/wav/exports.lds b/media/module/extractors/wav/exports.lds
similarity index 100%
rename from media/extractors/wav/exports.lds
rename to media/module/extractors/wav/exports.lds
diff --git a/media/extractors/wav/include/WAVExtractor.h b/media/module/extractors/wav/include/WAVExtractor.h
similarity index 100%
rename from media/extractors/wav/include/WAVExtractor.h
rename to media/module/extractors/wav/include/WAVExtractor.h
diff --git a/media/libstagefright/foundation/AAtomizer.cpp b/media/module/foundation/AAtomizer.cpp
similarity index 100%
rename from media/libstagefright/foundation/AAtomizer.cpp
rename to media/module/foundation/AAtomizer.cpp
diff --git a/media/libstagefright/foundation/ABitReader.cpp b/media/module/foundation/ABitReader.cpp
similarity index 100%
rename from media/libstagefright/foundation/ABitReader.cpp
rename to media/module/foundation/ABitReader.cpp
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/module/foundation/ABuffer.cpp
similarity index 100%
rename from media/libstagefright/foundation/ABuffer.cpp
rename to media/module/foundation/ABuffer.cpp
diff --git a/media/libstagefright/foundation/ADebug.cpp b/media/module/foundation/ADebug.cpp
similarity index 100%
rename from media/libstagefright/foundation/ADebug.cpp
rename to media/module/foundation/ADebug.cpp
diff --git a/media/libstagefright/foundation/AHandler.cpp b/media/module/foundation/AHandler.cpp
similarity index 100%
rename from media/libstagefright/foundation/AHandler.cpp
rename to media/module/foundation/AHandler.cpp
diff --git a/media/libstagefright/foundation/ALooper.cpp b/media/module/foundation/ALooper.cpp
similarity index 77%
rename from media/libstagefright/foundation/ALooper.cpp
rename to media/module/foundation/ALooper.cpp
index a276722..61bac02 100644
--- a/media/libstagefright/foundation/ALooper.cpp
+++ b/media/module/foundation/ALooper.cpp
@@ -69,6 +69,10 @@
     return systemTime(SYSTEM_TIME_MONOTONIC) / 1000LL;
 }
 
+int64_t ALooper::getNowUs() {
+    return GetNowUs();
+}
+
 ALooper::ALooper()
     : mRunningLocally(false) {
     // clean up stale AHandlers. Doing it here instead of in the destructor avoids
@@ -170,11 +174,11 @@
 
     int64_t whenUs;
     if (delayUs > 0) {
-        int64_t nowUs = GetNowUs();
+        int64_t nowUs = getNowUs();
         whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
 
     } else {
-        whenUs = GetNowUs();
+        whenUs = getNowUs();
     }
 
     List<Event>::iterator it = mEventQueue.begin();
@@ -185,6 +189,7 @@
     Event event;
     event.mWhenUs = whenUs;
     event.mMessage = msg;
+    event.mToken = nullptr;
 
     if (it == mEventQueue.begin()) {
         mQueueChangedCondition.signal();
@@ -193,7 +198,57 @@
     mEventQueue.insert(it, event);
 }
 
+status_t ALooper::postUnique(const sp<AMessage> &msg, const sp<RefBase> &token, int64_t delayUs) {
+    if (token == nullptr) {
+        return -EINVAL;
+    }
+    Mutex::Autolock autoLock(mLock);
+
+    int64_t whenUs;
+    if (delayUs > 0) {
+        int64_t nowUs = getNowUs();
+        whenUs = (delayUs > INT64_MAX - nowUs ? INT64_MAX : nowUs + delayUs);
+    } else {
+        whenUs = getNowUs();
+    }
+
+    // We only need to wake the loop up if we're rescheduling to the earliest event in the queue.
+    // This needs to be checked now, before we reschedule the message, in case this message is
+    // already at the beginning of the queue.
+    bool shouldAwakeLoop = mEventQueue.empty() || whenUs < mEventQueue.begin()->mWhenUs;
+
+    // Erase any previously-posted event with this token.
+    for (auto i = mEventQueue.begin(); i != mEventQueue.end();) {
+        if (i->mToken == token) {
+            i = mEventQueue.erase(i);
+        } else {
+            ++i;
+        }
+    }
+
+    // Find the insertion point for the rescheduled message.
+    List<Event>::iterator i = mEventQueue.begin();
+    while (i != mEventQueue.end() && i->mWhenUs <= whenUs) {
+        ++i;
+    }
+
+    Event event;
+    event.mWhenUs = whenUs;
+    event.mMessage = msg;
+    event.mToken = token;
+    mEventQueue.insert(i, event);
+
+    // If we rescheduled the event to be earlier than the first event, then we need to wake up the
+    // looper earlier than it was previously scheduled to be woken up. Otherwise, it can sleep until
+    // the previous wake-up time and then go to sleep again if needed.
+    if (shouldAwakeLoop){
+        mQueueChangedCondition.signal();
+    }
+    return OK;
+}
+
 bool ALooper::loop() {
+
     Event event;
 
     {
@@ -206,7 +261,7 @@
             return true;
         }
         int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
-        int64_t nowUs = GetNowUs();
+        int64_t nowUs = getNowUs();
 
         if (whenUs > nowUs) {
             int64_t delayUs = whenUs - nowUs;
diff --git a/media/libstagefright/foundation/ALooperRoster.cpp b/media/module/foundation/ALooperRoster.cpp
similarity index 100%
rename from media/libstagefright/foundation/ALooperRoster.cpp
rename to media/module/foundation/ALooperRoster.cpp
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/module/foundation/AMessage.cpp
similarity index 98%
rename from media/libstagefright/foundation/AMessage.cpp
rename to media/module/foundation/AMessage.cpp
index 5c99cc9..b61dc47 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/module/foundation/AMessage.cpp
@@ -430,6 +430,17 @@
     return OK;
 }
 
+status_t AMessage::postUnique(const sp<RefBase> &token, int64_t delayUs) {
+    sp<ALooper> looper = mLooper.promote();
+    if (looper == NULL) {
+        ALOGW("failed to post message as target looper for handler %d is gone.",
+              mTarget);
+        return -ENOENT;
+    }
+
+    return looper->postUnique(this, token, delayUs);
+}
+
 status_t AMessage::postAndAwaitResponse(sp<AMessage> *response) {
     sp<ALooper> looper = mLooper.promote();
     if (looper == NULL) {
diff --git a/media/libstagefright/foundation/AString.cpp b/media/module/foundation/AString.cpp
similarity index 100%
rename from media/libstagefright/foundation/AString.cpp
rename to media/module/foundation/AString.cpp
diff --git a/media/libstagefright/foundation/AStringUtils.cpp b/media/module/foundation/AStringUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/AStringUtils.cpp
rename to media/module/foundation/AStringUtils.cpp
diff --git a/media/libstagefright/foundation/Android.bp b/media/module/foundation/Android.bp
similarity index 100%
rename from media/libstagefright/foundation/Android.bp
rename to media/module/foundation/Android.bp
diff --git a/media/libstagefright/foundation/AudioPresentationInfo.cpp b/media/module/foundation/AudioPresentationInfo.cpp
similarity index 100%
rename from media/libstagefright/foundation/AudioPresentationInfo.cpp
rename to media/module/foundation/AudioPresentationInfo.cpp
diff --git a/media/libstagefright/foundation/ByteUtils.cpp b/media/module/foundation/ByteUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/ByteUtils.cpp
rename to media/module/foundation/ByteUtils.cpp
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/module/foundation/ColorUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/ColorUtils.cpp
rename to media/module/foundation/ColorUtils.cpp
diff --git a/media/libstagefright/foundation/ColorUtils_fill.cpp b/media/module/foundation/ColorUtils_fill.cpp
similarity index 100%
rename from media/libstagefright/foundation/ColorUtils_fill.cpp
rename to media/module/foundation/ColorUtils_fill.cpp
diff --git a/media/libstagefright/foundation/ColorUtils_ndk.cpp b/media/module/foundation/ColorUtils_ndk.cpp
similarity index 100%
rename from media/libstagefright/foundation/ColorUtils_ndk.cpp
rename to media/module/foundation/ColorUtils_ndk.cpp
diff --git a/media/libstagefright/foundation/FoundationUtils.cpp b/media/module/foundation/FoundationUtils.cpp
similarity index 100%
rename from media/libstagefright/foundation/FoundationUtils.cpp
rename to media/module/foundation/FoundationUtils.cpp
diff --git a/media/libstagefright/foundation/MODULE_LICENSE_APACHE2 b/media/module/foundation/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/foundation/MODULE_LICENSE_APACHE2
rename to media/module/foundation/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/foundation/MediaBuffer.cpp b/media/module/foundation/MediaBuffer.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBuffer.cpp
rename to media/module/foundation/MediaBuffer.cpp
diff --git a/media/libstagefright/foundation/MediaBufferBase.cpp b/media/module/foundation/MediaBufferBase.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBufferBase.cpp
rename to media/module/foundation/MediaBufferBase.cpp
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/module/foundation/MediaBufferGroup.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBufferGroup.cpp
rename to media/module/foundation/MediaBufferGroup.cpp
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/module/foundation/MediaDefs.cpp
similarity index 96%
rename from media/libstagefright/foundation/MediaDefs.cpp
rename to media/module/foundation/MediaDefs.cpp
index 5c4ec17..7abab63 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/module/foundation/MediaDefs.cpp
@@ -71,7 +71,10 @@
 const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM = "audio/x-adpcm-dvi-ima";
 const char *MEDIA_MIMETYPE_AUDIO_DTS = "audio/vnd.dts";
 const char *MEDIA_MIMETYPE_AUDIO_DTS_HD = "audio/vnd.dts.hd";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_HD_MA = "audio/vnd.dts.hd;profile=dtsma";
 const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD = "audio/vnd.dts.uhd";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1 = "audio/vnd.dts.uhd;profile=p1";
+const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2 = "audio/vnd.dts.uhd;profile=p2";
 const char *MEDIA_MIMETYPE_AUDIO_EVRC = "audio/evrc";
 const char *MEDIA_MIMETYPE_AUDIO_EVRCB = "audio/evrcb";
 const char *MEDIA_MIMETYPE_AUDIO_EVRCWB = "audio/evrcwb";
diff --git a/media/libstagefright/foundation/MediaKeys.cpp b/media/module/foundation/MediaKeys.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaKeys.cpp
rename to media/module/foundation/MediaKeys.cpp
diff --git a/media/libstagefright/foundation/MetaData.cpp b/media/module/foundation/MetaData.cpp
similarity index 100%
rename from media/libstagefright/foundation/MetaData.cpp
rename to media/module/foundation/MetaData.cpp
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/module/foundation/MetaDataBase.cpp
similarity index 100%
rename from media/libstagefright/foundation/MetaDataBase.cpp
rename to media/module/foundation/MetaDataBase.cpp
diff --git a/media/libstagefright/foundation/NOTICE b/media/module/foundation/NOTICE
similarity index 100%
rename from media/libstagefright/foundation/NOTICE
rename to media/module/foundation/NOTICE
diff --git a/media/libstagefright/foundation/OpusHeader.cpp b/media/module/foundation/OpusHeader.cpp
similarity index 100%
rename from media/libstagefright/foundation/OpusHeader.cpp
rename to media/module/foundation/OpusHeader.cpp
diff --git a/media/libstagefright/foundation/TEST_MAPPING b/media/module/foundation/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/foundation/TEST_MAPPING
rename to media/module/foundation/TEST_MAPPING
diff --git a/media/libstagefright/foundation/avc_utils.cpp b/media/module/foundation/avc_utils.cpp
similarity index 100%
rename from media/libstagefright/foundation/avc_utils.cpp
rename to media/module/foundation/avc_utils.cpp
diff --git a/media/libstagefright/foundation/base64.cpp b/media/module/foundation/base64.cpp
similarity index 100%
rename from media/libstagefright/foundation/base64.cpp
rename to media/module/foundation/base64.cpp
diff --git a/media/libstagefright/foundation/hexdump.cpp b/media/module/foundation/hexdump.cpp
similarity index 100%
rename from media/libstagefright/foundation/hexdump.cpp
rename to media/module/foundation/hexdump.cpp
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AAtomizer.h b/media/module/foundation/include/media/stagefright/foundation/AAtomizer.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AAtomizer.h
rename to media/module/foundation/include/media/stagefright/foundation/AAtomizer.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABase.h b/media/module/foundation/include/media/stagefright/foundation/ABase.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ABase.h
rename to media/module/foundation/include/media/stagefright/foundation/ABase.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABitReader.h b/media/module/foundation/include/media/stagefright/foundation/ABitReader.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ABitReader.h
rename to media/module/foundation/include/media/stagefright/foundation/ABitReader.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h b/media/module/foundation/include/media/stagefright/foundation/ABuffer.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h
rename to media/module/foundation/include/media/stagefright/foundation/ABuffer.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AData.h b/media/module/foundation/include/media/stagefright/foundation/AData.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AData.h
rename to media/module/foundation/include/media/stagefright/foundation/AData.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h b/media/module/foundation/include/media/stagefright/foundation/ADebug.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ADebug.h
rename to media/module/foundation/include/media/stagefright/foundation/ADebug.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h b/media/module/foundation/include/media/stagefright/foundation/AHandler.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AHandler.h
rename to media/module/foundation/include/media/stagefright/foundation/AHandler.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AHandlerReflector.h b/media/module/foundation/include/media/stagefright/foundation/AHandlerReflector.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AHandlerReflector.h
rename to media/module/foundation/include/media/stagefright/foundation/AHandlerReflector.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ALookup.h b/media/module/foundation/include/media/stagefright/foundation/ALookup.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ALookup.h
rename to media/module/foundation/include/media/stagefright/foundation/ALookup.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ALooper.h b/media/module/foundation/include/media/stagefright/foundation/ALooper.h
similarity index 85%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ALooper.h
rename to media/module/foundation/include/media/stagefright/foundation/ALooper.h
index 09c469b..60bda1f 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ALooper.h
+++ b/media/module/foundation/include/media/stagefright/foundation/ALooper.h
@@ -59,6 +59,9 @@
     }
 
 protected:
+    // overridable by test harness
+    virtual int64_t getNowUs();
+
     virtual ~ALooper();
 
 private:
@@ -67,6 +70,7 @@
     struct Event {
         int64_t mWhenUs;
         sp<AMessage> mMessage;
+        sp<RefBase> mToken;
     };
 
     Mutex mLock;
@@ -87,9 +91,14 @@
 
     // START --- methods used only by AMessage
 
-    // posts a message on this looper with the given timeout
+    // Posts a message on this looper with the given timeout.
     void post(const sp<AMessage> &msg, int64_t delayUs);
 
+    // Post a message uniquely on this looper with the given timeout.
+    // This method ensures that there is exactly one message with the same token pending posted on
+    // this looper after the call returns. A null token will result in an EINVAL error status.
+    status_t postUnique(const sp<AMessage> &msg, const sp<RefBase> &token, int64_t delayUs);
+
     // creates a reply token to be used with this looper
     sp<AReplyToken> createReplyToken();
     // waits for a response for the reply token.  If status is OK, the response
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ALooperRoster.h b/media/module/foundation/include/media/stagefright/foundation/ALooperRoster.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ALooperRoster.h
rename to media/module/foundation/include/media/stagefright/foundation/ALooperRoster.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h b/media/module/foundation/include/media/stagefright/foundation/AMessage.h
similarity index 97%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
rename to media/module/foundation/include/media/stagefright/foundation/AMessage.h
index 960212a..6f73597 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/AMessage.h
+++ b/media/module/foundation/include/media/stagefright/foundation/AMessage.h
@@ -141,6 +141,11 @@
 
     status_t post(int64_t delayUs = 0);
 
+    // Post a message uniquely to its target with the given timeout.
+    // This method ensures that there is exactly one message with the same token posted to its
+    // target after the call returns. A null token will result in an EINVAL error status.
+    status_t postUnique(const sp<RefBase> &token, int64_t delayUs = 0);
+
     // Posts the message to its target and waits for a response (or error)
     // before returning.
     status_t postAndAwaitResponse(sp<AMessage> *response);
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AString.h b/media/module/foundation/include/media/stagefright/foundation/AString.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AString.h
rename to media/module/foundation/include/media/stagefright/foundation/AString.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AStringUtils.h b/media/module/foundation/include/media/stagefright/foundation/AStringUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AStringUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/AStringUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AUtils.h b/media/module/foundation/include/media/stagefright/foundation/AUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/AUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h b/media/module/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h
rename to media/module/foundation/include/media/stagefright/foundation/AudioPresentationInfo.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ByteUtils.h b/media/module/foundation/include/media/stagefright/foundation/ByteUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ByteUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/ByteUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h b/media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
rename to media/module/foundation/include/media/stagefright/foundation/ColorUtils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/FileDescriptor.h b/media/module/foundation/include/media/stagefright/foundation/FileDescriptor.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/FileDescriptor.h
rename to media/module/foundation/include/media/stagefright/foundation/FileDescriptor.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/Flagged.h b/media/module/foundation/include/media/stagefright/foundation/Flagged.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/Flagged.h
rename to media/module/foundation/include/media/stagefright/foundation/Flagged.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/module/foundation/include/media/stagefright/foundation/MediaDefs.h
similarity index 97%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
rename to media/module/foundation/include/media/stagefright/foundation/MediaDefs.h
index fb8c299..05ee7fc 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/module/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -73,7 +73,10 @@
 extern const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
 extern const char *MEDIA_MIMETYPE_AUDIO_DTS;
 extern const char *MEDIA_MIMETYPE_AUDIO_DTS_HD;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_HD_MA;
 extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P1;
+extern const char *MEDIA_MIMETYPE_AUDIO_DTS_UHD_P2;
 extern const char *MEDIA_MIMETYPE_AUDIO_EVRC;
 extern const char *MEDIA_MIMETYPE_AUDIO_EVRCB;
 extern const char *MEDIA_MIMETYPE_AUDIO_EVRCWB;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaKeys.h b/media/module/foundation/include/media/stagefright/foundation/MediaKeys.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/MediaKeys.h
rename to media/module/foundation/include/media/stagefright/foundation/MediaKeys.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/Mutexed.h b/media/module/foundation/include/media/stagefright/foundation/Mutexed.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/Mutexed.h
rename to media/module/foundation/include/media/stagefright/foundation/Mutexed.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h b/media/module/foundation/include/media/stagefright/foundation/OpusHeader.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/OpusHeader.h
rename to media/module/foundation/include/media/stagefright/foundation/OpusHeader.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h b/media/module/foundation/include/media/stagefright/foundation/TypeTraits.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/TypeTraits.h
rename to media/module/foundation/include/media/stagefright/foundation/TypeTraits.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/avc_utils.h b/media/module/foundation/include/media/stagefright/foundation/avc_utils.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/avc_utils.h
rename to media/module/foundation/include/media/stagefright/foundation/avc_utils.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h b/media/module/foundation/include/media/stagefright/foundation/base64.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/base64.h
rename to media/module/foundation/include/media/stagefright/foundation/base64.h
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/hexdump.h b/media/module/foundation/include/media/stagefright/foundation/hexdump.h
similarity index 100%
rename from media/libstagefright/foundation/include/media/stagefright/foundation/hexdump.h
rename to media/module/foundation/include/media/stagefright/foundation/hexdump.h
diff --git a/media/libstagefright/foundation/tests/AData_test.cpp b/media/module/foundation/tests/AData_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/AData_test.cpp
rename to media/module/foundation/tests/AData_test.cpp
diff --git a/media/module/foundation/tests/AMessage_test.cpp b/media/module/foundation/tests/AMessage_test.cpp
new file mode 100644
index 0000000..e08ed77
--- /dev/null
+++ b/media/module/foundation/tests/AMessage_test.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AData_test"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/RefBase.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/ALooper.h>
+
+using namespace android;
+
+using ::testing::InSequence;
+using ::testing::NiceMock;
+
+class LooperWithSettableClock : public ALooper {
+public:
+  LooperWithSettableClock() : mClockUs(0) {}
+
+  void setClockUs(int64_t nowUs) {
+    mClockUs = nowUs;
+  }
+
+  int64_t getNowUs() override {
+    return mClockUs;
+  }
+
+private:
+  int64_t mClockUs;
+};
+
+timespec millis100 = {0, 100L*1000*1000};
+
+class MockHandler : public AHandler {
+public:
+    MOCK_METHOD(void, onMessageReceived, (const sp<AMessage>&), (override));
+};
+
+TEST(AMessage_tests, settersAndGetters) {
+  sp<AMessage> m1 = new AMessage();
+
+  m1->setInt32("value", 2);
+  m1->setInt32("bar", 3);
+
+  int32_t i32;
+  EXPECT_TRUE(m1->findInt32("value", &i32));
+  EXPECT_EQ(2, i32);
+
+  EXPECT_TRUE(m1->findInt32("bar", &i32));
+  EXPECT_EQ(3, i32);
+
+
+  m1->setInt64("big", INT64_MAX);
+  m1->setInt64("smaller", INT64_MAX - 2);
+  m1->setInt64("smallest", 257);
+
+  int64_t i64;
+  EXPECT_TRUE(m1->findInt64("big", &i64));
+  EXPECT_EQ(INT64_MAX, i64);
+
+  EXPECT_TRUE(m1->findInt64("smaller", &i64));
+  EXPECT_EQ(INT64_MAX - 2, i64);
+
+  m1->setSize("size1", 257);
+  m1->setSize("size2", 1023);
+
+  size_t sizing;
+  EXPECT_TRUE(m1->findSize("size2", &sizing));
+  EXPECT_EQ(1023, sizing);
+  EXPECT_TRUE(m1->findSize("size1", &sizing));
+  EXPECT_EQ(257, sizing);
+
+  m1->setDouble("precise", 10.5);
+  m1->setDouble("small", 0.125);
+
+  double d;
+  EXPECT_TRUE(m1->findDouble("precise", &d));
+  EXPECT_EQ(10.5, d);
+
+  EXPECT_TRUE(m1->findDouble("small", &d));
+  EXPECT_EQ(0.125, d);
+
+  // should be unchanged from the top of the test
+  EXPECT_TRUE(m1->findInt32("bar", &i32));
+  EXPECT_EQ(3, i32);
+
+  EXPECT_FALSE(m1->findInt32("nonesuch", &i32));
+  EXPECT_FALSE(m1->findInt64("nonesuch2", &i64));
+  // types disagree, not found
+  EXPECT_FALSE(m1->findInt32("big", &i32));
+  EXPECT_FALSE(m1->findInt32("precise", &i32));
+
+  // integral types should come back true
+  EXPECT_TRUE(m1->findAsInt64("big", &i64));
+  EXPECT_EQ(INT64_MAX, i64);
+  EXPECT_TRUE(m1->findAsInt64("bar", &i64));
+  EXPECT_EQ(3, i64);
+  EXPECT_FALSE(m1->findAsInt64("precise", &i64));
+
+  // recovers ints, size, and floating point values
+  float value;
+  EXPECT_TRUE(m1->findAsFloat("value", &value));
+  EXPECT_EQ(2, value);
+  EXPECT_TRUE(m1->findAsFloat("smallest", &value));
+  EXPECT_EQ(257, value);
+  EXPECT_TRUE(m1->findAsFloat("size2", &value));
+  EXPECT_EQ(1023, value);
+  EXPECT_TRUE(m1->findAsFloat("precise", &value));
+  EXPECT_EQ(10.5, value);
+  EXPECT_TRUE(m1->findAsFloat("small", &value));
+  EXPECT_EQ(0.125, value);
+
+
+  // need to handle still:
+  // strings
+  // Object
+  // Buffer
+  // Message (nested)
+  //
+
+  // removal
+  m1->setInt32("shortlived", 2);
+  m1->setInt32("alittlelonger", 2);
+  EXPECT_EQ(OK, m1->removeEntryByName("shortlived"));
+  EXPECT_EQ(BAD_VALUE, m1->removeEntryByName(nullptr));
+  EXPECT_EQ(BAD_INDEX, m1->removeEntryByName("themythicalnonesuch"));
+  EXPECT_FALSE(m1->findInt32("shortlived", &i32));
+  EXPECT_TRUE(m1->findInt32("alittlelonger", &i32));
+
+  EXPECT_NE(OK, m1->removeEntryByName("notpresent"));
+}
+
+TEST(AMessage_tests, deliversMultipleMessagesInOrderImmediately) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msgNow1 = new AMessage(0, mockHandler);
+  msgNow1->post();
+  sp<AMessage> msgNow2 = new AMessage(0, mockHandler);
+  msgNow2->post();
+
+  {
+    InSequence inSequence;
+    EXPECT_CALL(*mockHandler, onMessageReceived(msgNow1)).Times(1);
+    EXPECT_CALL(*mockHandler, onMessageReceived(msgNow2)).Times(1);
+  }
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, doesNotDeliverDelayedMessageImmediately) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msgNow = new AMessage(0, mockHandler);
+  msgNow->post();
+  sp<AMessage> msgDelayed = new AMessage(0, mockHandler);
+  msgDelayed->post(100);
+
+  EXPECT_CALL(*mockHandler, onMessageReceived(msgNow)).Times(1);
+  // note: never called
+  EXPECT_CALL(*mockHandler, onMessageReceived(msgDelayed)).Times(0);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversDelayedMessagesInSequence) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msgIn500 = new AMessage(0, mockHandler);
+  msgIn500->post(500);
+  sp<AMessage> msgNow = new AMessage(0, mockHandler);
+  msgNow->post();
+  sp<AMessage> msgIn100 = new AMessage(0, mockHandler);
+  msgIn100->post(100);
+  // not expected to be received
+  sp<AMessage> msgIn1000 = new AMessage(0, mockHandler);
+  msgIn1000->post(1000);
+
+  looper->setClockUs(500);
+  {
+    InSequence inSequence;
+
+    EXPECT_CALL(*mockHandler, onMessageReceived(msgNow)).Times(1);
+    EXPECT_CALL(*mockHandler, onMessageReceived(msgIn100)).Times(1);
+    EXPECT_CALL(*mockHandler, onMessageReceived(msgIn500)).Times(1);
+  }
+  // note: never called
+  EXPECT_CALL(*mockHandler, onMessageReceived(msgIn1000)).Times(0);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversDelayedUniqueMessage) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg = new AMessage(0, mockHandler);
+  msg->postUnique(msg, 50);
+
+  looper->setClockUs(50);
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(1);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversImmediateUniqueMessage) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  // note: we don't need to set the clock, but we do want a stable clock that doesn't advance
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg = new AMessage(0, mockHandler);
+  msg->postUnique(msg, 0);
+
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(1);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, doesNotDeliverUniqueMessageAfterRescheduleLater) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg = new AMessage(0, mockHandler);
+  msg->postUnique(msg, 50);
+  msg->postUnique(msg, 100); // reschedule for later
+
+  looper->setClockUs(50); // if the message is correctly rescheduled, it should not be delivered
+  // Never called because the message was rescheduled to a later point in time
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(0);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversUniqueMessageAfterRescheduleEarlier) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg = new AMessage(0, mockHandler);
+  msg->postUnique(msg, 100);
+  msg->postUnique(msg, 50); // reschedule to fire earlier
+
+  looper->setClockUs(50); // if the message is rescheduled correctly, it should be delivered
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(1);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, deliversSameMessageTwice) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg = new AMessage(0, mockHandler);
+  msg->post(50);
+  msg->post(100);
+
+  looper->setClockUs(100);
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg)).Times(2);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+// When messages are posted twice with the same token, it will only be delivered once after being
+// rescheduled.
+TEST(AMessage_tests, deliversUniqueMessageOnce) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<LooperWithSettableClock> looper = new LooperWithSettableClock();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg1 = new AMessage(0, mockHandler);
+  msg1->postUnique(msg1, 50);
+  sp<AMessage> msg2 = new AMessage(0, mockHandler);
+  msg2->postUnique(msg1, 75); // note, using the same token as msg1
+
+  looper->setClockUs(100);
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg1)).Times(0);
+  EXPECT_CALL(*mockHandler, onMessageReceived(msg2)).Times(1);
+  looper->start();
+  nanosleep(&millis100, nullptr); // just enough time for the looper thread to run
+}
+
+TEST(AMessage_tests, postUnique_withNullToken_returnsInvalidArgument) {
+  sp<NiceMock<MockHandler>> mockHandler = new NiceMock<MockHandler>;
+  sp<ALooper> looper = new ALooper();
+  looper->registerHandler(mockHandler);
+
+  sp<AMessage> msg = new AMessage(0, mockHandler);
+  EXPECT_EQ(msg->postUnique(nullptr, 0), -EINVAL);
+}
diff --git a/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h b/media/module/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h
rename to media/module/foundation/tests/AVCUtils/AVCUtilsTestEnvironment.h
diff --git a/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
similarity index 92%
rename from media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
rename to media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
index 77a8599..57ac822 100644
--- a/media/libstagefright/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
+++ b/media/module/foundation/tests/AVCUtils/AVCUtilsUnitTest.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include <fstream>
+#include <memory>
 
 #include "media/stagefright/foundation/ABitReader.h"
 #include "media/stagefright/foundation/avc_utils.h"
@@ -151,10 +152,10 @@
     size_t fileSize = buf.st_size;
     ASSERT_NE(fileSize, 0) << "Invalid file size found";
 
-    const uint8_t *volBuffer = new uint8_t[fileSize];
+    std::unique_ptr<uint8_t[]> volBuffer(new uint8_t[fileSize]);
     ASSERT_NE(volBuffer, nullptr) << "Failed to allocate VOL buffer of size: " << fileSize;
 
-    inputFileStream.read((char *)(volBuffer), fileSize);
+    inputFileStream.read((char *)(volBuffer.get()), fileSize);
     ASSERT_EQ(inputFileStream.gcount(), fileSize)
             << "Failed to read complete file, bytes read: " << inputFileStream.gcount();
 
@@ -163,15 +164,13 @@
     int32_t volWidth = -1;
     int32_t volHeight = -1;
 
-    bool status = ExtractDimensionsFromVOLHeader(volBuffer, fileSize, &volWidth, &volHeight);
+    bool status = ExtractDimensionsFromVOLHeader(volBuffer.get(), fileSize, &volWidth, &volHeight);
     ASSERT_TRUE(status)
             << "Failed to get VOL dimensions from function: ExtractDimensionsFromVOLHeader()";
 
     ASSERT_EQ(volWidth, width) << "Expected width: " << width << "Found: " << volWidth;
 
     ASSERT_EQ(volHeight, height) << "Expected height: " << height << "Found: " << volHeight;
-
-    delete[] volBuffer;
 }
 
 TEST_P(AVCDimensionTest, DimensionTest) {
@@ -186,7 +185,8 @@
         stringLine >> type >> chunkLength;
         ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
 
-        const uint8_t *data = new uint8_t[chunkLength];
+        std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+        const uint8_t *data = dataArray.get();
         ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
 
         const uint8_t *nalStart;
@@ -197,9 +197,11 @@
                 << "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
 
         size_t smallBufferSize = kSmallBufferSize;
-        const uint8_t *sanityData = new uint8_t[smallBufferSize];
+        uint8_t sanityDataBuffer[smallBufferSize];
+        const uint8_t *sanityData = sanityDataBuffer;
         memcpy((void *)sanityData, (void *)data, smallBufferSize);
 
+        // sanityData could be changed, but sanityDataPtr is not and can be cleaned up.
         status_t result = getNextNALUnit(&sanityData, &smallBufferSize, &nalStart, &nalSize, true);
         ASSERT_EQ(result, -EAGAIN) << "Invalid result found when wrong NAL unit passed";
 
@@ -221,7 +223,6 @@
             ASSERT_EQ(avcHeight, mFrameHeight)
                     << "Expected height: " << mFrameHeight << "Found: " << avcHeight;
         }
-        delete[] data;
     }
     if (mNalUnitsExpected < 0) {
         ASSERT_GT(numNalUnits, 0) << "Failed to find an NAL Unit";
@@ -251,7 +252,8 @@
         accessUnitLength += chunkLength;
 
         if (!type.compare("SPS")) {
-            const uint8_t *data = new uint8_t[chunkLength];
+            std::unique_ptr<uint8_t[]> dataArray(new uint8_t[chunkLength]);
+            const uint8_t *data = dataArray.get();
             ASSERT_NE(data, nullptr) << "Failed to create a data buffer of size: " << chunkLength;
 
             const uint8_t *nalStart;
@@ -271,14 +273,13 @@
                 profile = nalStart[1];
                 level = nalStart[3];
             }
-            delete[] data;
         }
     }
-    const uint8_t *accessUnitData = new uint8_t[accessUnitLength];
+    std::unique_ptr<uint8_t[]> accessUnitData(new uint8_t[accessUnitLength]);
     ASSERT_NE(accessUnitData, nullptr) << "Failed to create a buffer of size: " << accessUnitLength;
 
     mInputFileStream.seekg(0, ios::beg);
-    mInputFileStream.read((char *)accessUnitData, accessUnitLength);
+    mInputFileStream.read((char *)accessUnitData.get(), accessUnitLength);
     ASSERT_EQ(mInputFileStream.gcount(), accessUnitLength)
             << "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
 
@@ -286,7 +287,7 @@
     ASSERT_NE(accessUnit, nullptr)
             << "Failed to create an android data buffer of size: " << accessUnitLength;
 
-    memcpy(accessUnit->data(), accessUnitData, accessUnitLength);
+    memcpy(accessUnit->data(), accessUnitData.get(), accessUnitLength);
     sp<ABuffer> csdDataBuffer = MakeAVCCodecSpecificData(accessUnit, &avcWidth, &avcHeight);
     ASSERT_NE(csdDataBuffer, nullptr) << "No data returned from MakeAVCCodecSpecificData()";
 
@@ -306,7 +307,6 @@
     ASSERT_EQ(*(csdData + 3), level)
             << "Expected AVC level: " << level << " found: " << *(csdData + 3);
     csdDataBuffer.clear();
-    delete[] accessUnitData;
     accessUnit.clear();
 }
 
@@ -321,32 +321,31 @@
         stringLine >> type >> chunkLength >> frameLayerID;
         ASSERT_GT(chunkLength, 0) << "Length of the data chunk must be greater than zero";
 
-        char *data = new char[chunkLength];
+        std::unique_ptr<char[]> data(new char[chunkLength]);
         ASSERT_NE(data, nullptr) << "Failed to allocation data buffer of size: " << chunkLength;
 
-        mInputFileStream.read(data, chunkLength);
+        mInputFileStream.read(data.get(), chunkLength);
         ASSERT_EQ(mInputFileStream.gcount(), chunkLength)
                 << "Failed to read complete file, bytes read: " << mInputFileStream.gcount();
 
         if (!type.compare("IDR")) {
-            bool isIDR = IsIDR((uint8_t *)data, chunkLength);
+            bool isIDR = IsIDR((uint8_t *)data.get(), chunkLength);
             ASSERT_TRUE(isIDR);
 
-            layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+            layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
             ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
         } else if (!type.compare("P") || !type.compare("B")) {
             sp<ABuffer> accessUnit = new ABuffer(chunkLength);
             ASSERT_NE(accessUnit, nullptr) << "Unable to create access Unit";
 
-            memcpy(accessUnit->data(), data, chunkLength);
+            memcpy(accessUnit->data(), data.get(), chunkLength);
             bool isReferenceFrame = IsAVCReferenceFrame(accessUnit);
             ASSERT_TRUE(isReferenceFrame);
 
             accessUnit.clear();
-            layerID = FindAVCLayerId((uint8_t *)data, chunkLength);
+            layerID = FindAVCLayerId((uint8_t *)data.get(), chunkLength);
             ASSERT_EQ(layerID, frameLayerID) << "Wrong layer ID found";
         }
-        delete[] data;
     }
 }
 
diff --git a/media/libstagefright/foundation/tests/AVCUtils/Android.bp b/media/module/foundation/tests/AVCUtils/Android.bp
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/Android.bp
rename to media/module/foundation/tests/AVCUtils/Android.bp
diff --git a/media/libstagefright/foundation/tests/AVCUtils/AndroidTest.xml b/media/module/foundation/tests/AVCUtils/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/AndroidTest.xml
rename to media/module/foundation/tests/AVCUtils/AndroidTest.xml
diff --git a/media/libstagefright/foundation/tests/AVCUtils/README.md b/media/module/foundation/tests/AVCUtils/README.md
similarity index 100%
rename from media/libstagefright/foundation/tests/AVCUtils/README.md
rename to media/module/foundation/tests/AVCUtils/README.md
diff --git a/media/libstagefright/foundation/tests/Android.bp b/media/module/foundation/tests/Android.bp
similarity index 96%
rename from media/libstagefright/foundation/tests/Android.bp
rename to media/module/foundation/tests/Android.bp
index e72ce43..c409dd2 100644
--- a/media/libstagefright/foundation/tests/Android.bp
+++ b/media/module/foundation/tests/Android.bp
@@ -20,10 +20,14 @@
 
     shared_libs: [
         "liblog",
-        "libstagefright_foundation",
         "libutils",
     ],
 
+    static_libs: [
+        "libstagefright_foundation",
+        "libgmock",
+    ],
+
     srcs: [
         "AData_test.cpp",
         "AMessage_test.cpp",
diff --git a/media/libstagefright/foundation/tests/Base64_test.cpp b/media/module/foundation/tests/Base64_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/Base64_test.cpp
rename to media/module/foundation/tests/Base64_test.cpp
diff --git a/media/libstagefright/foundation/tests/Flagged_test.cpp b/media/module/foundation/tests/Flagged_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/Flagged_test.cpp
rename to media/module/foundation/tests/Flagged_test.cpp
diff --git a/media/libstagefright/foundation/tests/MetaDataBaseUnitTest.cpp b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
similarity index 96%
rename from media/libstagefright/foundation/tests/MetaDataBaseUnitTest.cpp
rename to media/module/foundation/tests/MetaDataBaseUnitTest.cpp
index 0aed4d2..b562e07 100644
--- a/media/libstagefright/foundation/tests/MetaDataBaseUnitTest.cpp
+++ b/media/module/foundation/tests/MetaDataBaseUnitTest.cpp
@@ -19,6 +19,7 @@
 #include <string.h>
 #include <sys/stat.h>
 #include <fstream>
+#include <memory>
 
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaDataBase.h>
@@ -48,18 +49,16 @@
 class MetaDataBaseUnitTest : public ::testing::Test {};
 
 TEST_F(MetaDataBaseUnitTest, CreateMetaDataBaseTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     // Testing copy constructor
-    MetaDataBase *metaDataCopy = metaData;
+    MetaDataBase *metaDataCopy = metaData.get();
     ASSERT_NE(metaDataCopy, nullptr) << "Failed to create meta data copy";
-
-    delete metaData;
 }
 
 TEST_F(MetaDataBaseUnitTest, SetAndFindDataTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     // Setting the different key-value pair type for first time, overwrite
@@ -142,12 +141,10 @@
     int32_t angle;
     status = metaData->findInt32(kKeyRotation, &angle);
     ASSERT_FALSE(status) << "Value for an invalid key is returned when the key is not set";
-
-    delete (metaData);
 }
 
 TEST_F(MetaDataBaseUnitTest, OverWriteFunctionalityTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     // set/set/read to check first overwrite operation
@@ -186,12 +183,10 @@
     status = metaData->findInt32(kKeyHeight, &height);
     ASSERT_TRUE(status) << "kKeyHeight key does not exists in metadata";
     ASSERT_EQ(height, kHeight3) << "Value of height is not overwritten";
-
-    delete (metaData);
 }
 
 TEST_F(MetaDataBaseUnitTest, RemoveKeyTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     bool status = metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -246,12 +241,10 @@
 
     metaData->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
     ASSERT_FALSE(status) << "Overwrite should be false since the metadata was cleared";
-
-    delete (metaData);
 }
 
 TEST_F(MetaDataBaseUnitTest, ConvertToStringTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     String8 info = metaData->toString();
@@ -281,8 +274,6 @@
     info = metaData->toString();
     ASSERT_EQ(info.length(), 0) << "MetaData length is non-zero after clearing it: "
                                 << info.length();
-
-    delete (metaData);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/foundation/tests/OpusHeader/Android.bp b/media/module/foundation/tests/OpusHeader/Android.bp
similarity index 89%
rename from media/libstagefright/foundation/tests/OpusHeader/Android.bp
rename to media/module/foundation/tests/OpusHeader/Android.bp
index fa2b40e..f052650 100644
--- a/media/libstagefright/foundation/tests/OpusHeader/Android.bp
+++ b/media/module/foundation/tests/OpusHeader/Android.bp
@@ -54,4 +54,7 @@
         ],
         cfi: true,
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/foundation/tests/OpusHeader/OpusHeader.zip?unzip=true",
+    ],
 }
diff --git a/media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml b/media/module/foundation/tests/OpusHeader/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/AndroidTest.xml
rename to media/module/foundation/tests/OpusHeader/AndroidTest.xml
diff --git a/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp b/media/module/foundation/tests/OpusHeader/OpusHeaderTest.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTest.cpp
rename to media/module/foundation/tests/OpusHeader/OpusHeaderTest.cpp
diff --git a/media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h b/media/module/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
rename to media/module/foundation/tests/OpusHeader/OpusHeaderTestEnvironment.h
diff --git a/media/libstagefright/foundation/tests/OpusHeader/README.md b/media/module/foundation/tests/OpusHeader/README.md
similarity index 100%
rename from media/libstagefright/foundation/tests/OpusHeader/README.md
rename to media/module/foundation/tests/OpusHeader/README.md
diff --git a/media/libstagefright/foundation/tests/TypeTraits_test.cpp b/media/module/foundation/tests/TypeTraits_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/TypeTraits_test.cpp
rename to media/module/foundation/tests/TypeTraits_test.cpp
diff --git a/media/libstagefright/foundation/tests/Utils_test.cpp b/media/module/foundation/tests/Utils_test.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/Utils_test.cpp
rename to media/module/foundation/tests/Utils_test.cpp
diff --git a/media/libstagefright/foundation/tests/colorutils/Android.bp b/media/module/foundation/tests/colorutils/Android.bp
similarity index 100%
rename from media/libstagefright/foundation/tests/colorutils/Android.bp
rename to media/module/foundation/tests/colorutils/Android.bp
diff --git a/media/libstagefright/foundation/tests/colorutils/ColorUtilsTest.cpp b/media/module/foundation/tests/colorutils/ColorUtilsTest.cpp
similarity index 100%
rename from media/libstagefright/foundation/tests/colorutils/ColorUtilsTest.cpp
rename to media/module/foundation/tests/colorutils/ColorUtilsTest.cpp
diff --git a/media/libstagefright/id3/Android.bp b/media/module/id3/Android.bp
similarity index 100%
rename from media/libstagefright/id3/Android.bp
rename to media/module/id3/Android.bp
diff --git a/media/libstagefright/id3/ID3.cpp b/media/module/id3/ID3.cpp
similarity index 100%
rename from media/libstagefright/id3/ID3.cpp
rename to media/module/id3/ID3.cpp
diff --git a/media/libstagefright/id3/MODULE_LICENSE_APACHE2 b/media/module/id3/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/id3/MODULE_LICENSE_APACHE2
rename to media/module/id3/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/id3/NOTICE b/media/module/id3/NOTICE
similarity index 100%
rename from media/libstagefright/id3/NOTICE
rename to media/module/id3/NOTICE
diff --git a/media/libstagefright/id3/TEST_MAPPING b/media/module/id3/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/id3/TEST_MAPPING
rename to media/module/id3/TEST_MAPPING
diff --git a/media/libstagefright/id3/test/Android.bp b/media/module/id3/test/Android.bp
similarity index 91%
rename from media/libstagefright/id3/test/Android.bp
rename to media/module/id3/test/Android.bp
index 52cdfa5..0481e48 100644
--- a/media/libstagefright/id3/test/Android.bp
+++ b/media/module/id3/test/Android.bp
@@ -57,4 +57,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/id3/test/ID3Test-1.2.zip?unzip=true",
+    ],
 }
diff --git a/media/libstagefright/id3/test/AndroidTest.xml b/media/module/id3/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/id3/test/AndroidTest.xml
rename to media/module/id3/test/AndroidTest.xml
diff --git a/media/libstagefright/id3/test/ID3Test.cpp b/media/module/id3/test/ID3Test.cpp
similarity index 100%
rename from media/libstagefright/id3/test/ID3Test.cpp
rename to media/module/id3/test/ID3Test.cpp
diff --git a/media/libstagefright/id3/test/ID3TestEnvironment.h b/media/module/id3/test/ID3TestEnvironment.h
similarity index 100%
rename from media/libstagefright/id3/test/ID3TestEnvironment.h
rename to media/module/id3/test/ID3TestEnvironment.h
diff --git a/media/libstagefright/id3/test/README.md b/media/module/id3/test/README.md
similarity index 100%
rename from media/libstagefright/id3/test/README.md
rename to media/module/id3/test/README.md
diff --git a/media/libstagefright/id3/testid3.cpp b/media/module/id3/testid3.cpp
similarity index 100%
rename from media/libstagefright/id3/testid3.cpp
rename to media/module/id3/testid3.cpp
diff --git a/media/libmediaformatshaper/Android.bp b/media/module/libmediaformatshaper/Android.bp
similarity index 100%
rename from media/libmediaformatshaper/Android.bp
rename to media/module/libmediaformatshaper/Android.bp
diff --git a/media/libmediaformatshaper/CodecProperties.cpp b/media/module/libmediaformatshaper/CodecProperties.cpp
similarity index 100%
rename from media/libmediaformatshaper/CodecProperties.cpp
rename to media/module/libmediaformatshaper/CodecProperties.cpp
diff --git a/media/libmediaformatshaper/CodecProperties.h b/media/module/libmediaformatshaper/CodecProperties.h
similarity index 100%
rename from media/libmediaformatshaper/CodecProperties.h
rename to media/module/libmediaformatshaper/CodecProperties.h
diff --git a/media/libmediaformatshaper/CodecSeeding.cpp b/media/module/libmediaformatshaper/CodecSeeding.cpp
similarity index 100%
rename from media/libmediaformatshaper/CodecSeeding.cpp
rename to media/module/libmediaformatshaper/CodecSeeding.cpp
diff --git a/media/libmediaformatshaper/FormatShaper.cpp b/media/module/libmediaformatshaper/FormatShaper.cpp
similarity index 100%
rename from media/libmediaformatshaper/FormatShaper.cpp
rename to media/module/libmediaformatshaper/FormatShaper.cpp
diff --git a/media/libmediaformatshaper/ManageShapingCodecs.cpp b/media/module/libmediaformatshaper/ManageShapingCodecs.cpp
similarity index 100%
rename from media/libmediaformatshaper/ManageShapingCodecs.cpp
rename to media/module/libmediaformatshaper/ManageShapingCodecs.cpp
diff --git a/media/libmediaformatshaper/VQApply.cpp b/media/module/libmediaformatshaper/VQApply.cpp
similarity index 100%
rename from media/libmediaformatshaper/VQApply.cpp
rename to media/module/libmediaformatshaper/VQApply.cpp
diff --git a/media/libmediaformatshaper/VQops.h b/media/module/libmediaformatshaper/VQops.h
similarity index 100%
rename from media/libmediaformatshaper/VQops.h
rename to media/module/libmediaformatshaper/VQops.h
diff --git a/media/libmediaformatshaper/VideoShaper.cpp b/media/module/libmediaformatshaper/VideoShaper.cpp
similarity index 100%
rename from media/libmediaformatshaper/VideoShaper.cpp
rename to media/module/libmediaformatshaper/VideoShaper.cpp
diff --git a/media/libmediaformatshaper/VideoShaper.h b/media/module/libmediaformatshaper/VideoShaper.h
similarity index 100%
rename from media/libmediaformatshaper/VideoShaper.h
rename to media/module/libmediaformatshaper/VideoShaper.h
diff --git a/media/libmediaformatshaper/exports.lds b/media/module/libmediaformatshaper/exports.lds
similarity index 100%
rename from media/libmediaformatshaper/exports.lds
rename to media/module/libmediaformatshaper/exports.lds
diff --git a/media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h b/media/module/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
similarity index 100%
rename from media/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
rename to media/module/libmediaformatshaper/include/media/formatshaper/FormatShaper.h
diff --git a/media/libmediatranscoding/.clang-format b/media/module/libmediatranscoding/.clang-format
similarity index 100%
rename from media/libmediatranscoding/.clang-format
rename to media/module/libmediatranscoding/.clang-format
diff --git a/media/libmediatranscoding/Android.bp b/media/module/libmediatranscoding/Android.bp
similarity index 100%
rename from media/libmediatranscoding/Android.bp
rename to media/module/libmediatranscoding/Android.bp
diff --git a/media/libmediatranscoding/OWNERS b/media/module/libmediatranscoding/OWNERS
similarity index 100%
rename from media/libmediatranscoding/OWNERS
rename to media/module/libmediatranscoding/OWNERS
diff --git a/media/libmediatranscoding/TEST_MAPPING b/media/module/libmediatranscoding/TEST_MAPPING
similarity index 100%
rename from media/libmediatranscoding/TEST_MAPPING
rename to media/module/libmediatranscoding/TEST_MAPPING
diff --git a/media/libmediatranscoding/TranscoderWrapper.cpp b/media/module/libmediatranscoding/TranscoderWrapper.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscoderWrapper.cpp
rename to media/module/libmediatranscoding/TranscoderWrapper.cpp
diff --git a/media/libmediatranscoding/TranscodingClientManager.cpp b/media/module/libmediatranscoding/TranscodingClientManager.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingClientManager.cpp
rename to media/module/libmediatranscoding/TranscodingClientManager.cpp
diff --git a/media/libmediatranscoding/TranscodingLogger.cpp b/media/module/libmediatranscoding/TranscodingLogger.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingLogger.cpp
rename to media/module/libmediatranscoding/TranscodingLogger.cpp
diff --git a/media/libmediatranscoding/TranscodingResourcePolicy.cpp b/media/module/libmediatranscoding/TranscodingResourcePolicy.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingResourcePolicy.cpp
rename to media/module/libmediatranscoding/TranscodingResourcePolicy.cpp
diff --git a/media/libmediatranscoding/TranscodingSessionController.cpp b/media/module/libmediatranscoding/TranscodingSessionController.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingSessionController.cpp
rename to media/module/libmediatranscoding/TranscodingSessionController.cpp
diff --git a/media/libmediatranscoding/TranscodingThermalPolicy.cpp b/media/module/libmediatranscoding/TranscodingThermalPolicy.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingThermalPolicy.cpp
rename to media/module/libmediatranscoding/TranscodingThermalPolicy.cpp
diff --git a/media/libmediatranscoding/TranscodingUidPolicy.cpp b/media/module/libmediatranscoding/TranscodingUidPolicy.cpp
similarity index 100%
rename from media/libmediatranscoding/TranscodingUidPolicy.cpp
rename to media/module/libmediatranscoding/TranscodingUidPolicy.cpp
diff --git a/media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl b/media/module/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
rename to media/module/libmediatranscoding/aidl/android/media/IMediaTranscodingService.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl b/media/module/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
rename to media/module/libmediatranscoding/aidl/android/media/ITranscodingClient.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl b/media/module/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
rename to media/module/libmediatranscoding/aidl/android/media/ITranscodingClientCallback.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingErrorCode.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingRequestParcel.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingResultParcel.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingSessionParcel.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingSessionPriority.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingSessionStats.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingTestConfig.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingType.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingType.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingType.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingType.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingVideoCodecType.aidl
diff --git a/media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl b/media/module/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
similarity index 100%
rename from media/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
rename to media/module/libmediatranscoding/aidl/android/media/TranscodingVideoTrackFormat.aidl
diff --git a/media/libmediatranscoding/build_and_run_all_unit_tests.sh b/media/module/libmediatranscoding/build_and_run_all_unit_tests.sh
similarity index 100%
rename from media/libmediatranscoding/build_and_run_all_unit_tests.sh
rename to media/module/libmediatranscoding/build_and_run_all_unit_tests.sh
diff --git a/media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h b/media/module/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
similarity index 100%
rename from media/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
rename to media/module/libmediatranscoding/include/media/AdjustableMaxPriorityQueue.h
diff --git a/media/libmediatranscoding/include/media/ControllerClientInterface.h b/media/module/libmediatranscoding/include/media/ControllerClientInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/ControllerClientInterface.h
rename to media/module/libmediatranscoding/include/media/ControllerClientInterface.h
diff --git a/media/libmediatranscoding/include/media/ResourcePolicyInterface.h b/media/module/libmediatranscoding/include/media/ResourcePolicyInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/ResourcePolicyInterface.h
rename to media/module/libmediatranscoding/include/media/ResourcePolicyInterface.h
diff --git a/media/libmediatranscoding/include/media/ThermalPolicyInterface.h b/media/module/libmediatranscoding/include/media/ThermalPolicyInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/ThermalPolicyInterface.h
rename to media/module/libmediatranscoding/include/media/ThermalPolicyInterface.h
diff --git a/media/libmediatranscoding/include/media/TranscoderInterface.h b/media/module/libmediatranscoding/include/media/TranscoderInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscoderInterface.h
rename to media/module/libmediatranscoding/include/media/TranscoderInterface.h
diff --git a/media/libmediatranscoding/include/media/TranscoderWrapper.h b/media/module/libmediatranscoding/include/media/TranscoderWrapper.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscoderWrapper.h
rename to media/module/libmediatranscoding/include/media/TranscoderWrapper.h
diff --git a/media/libmediatranscoding/include/media/TranscodingClientManager.h b/media/module/libmediatranscoding/include/media/TranscodingClientManager.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingClientManager.h
rename to media/module/libmediatranscoding/include/media/TranscodingClientManager.h
diff --git a/media/libmediatranscoding/include/media/TranscodingDefs.h b/media/module/libmediatranscoding/include/media/TranscodingDefs.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingDefs.h
rename to media/module/libmediatranscoding/include/media/TranscodingDefs.h
diff --git a/media/libmediatranscoding/include/media/TranscodingLogger.h b/media/module/libmediatranscoding/include/media/TranscodingLogger.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingLogger.h
rename to media/module/libmediatranscoding/include/media/TranscodingLogger.h
diff --git a/media/libmediatranscoding/include/media/TranscodingRequest.h b/media/module/libmediatranscoding/include/media/TranscodingRequest.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingRequest.h
rename to media/module/libmediatranscoding/include/media/TranscodingRequest.h
diff --git a/media/libmediatranscoding/include/media/TranscodingResourcePolicy.h b/media/module/libmediatranscoding/include/media/TranscodingResourcePolicy.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingResourcePolicy.h
rename to media/module/libmediatranscoding/include/media/TranscodingResourcePolicy.h
diff --git a/media/libmediatranscoding/include/media/TranscodingSessionController.h b/media/module/libmediatranscoding/include/media/TranscodingSessionController.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingSessionController.h
rename to media/module/libmediatranscoding/include/media/TranscodingSessionController.h
diff --git a/media/libmediatranscoding/include/media/TranscodingThermalPolicy.h b/media/module/libmediatranscoding/include/media/TranscodingThermalPolicy.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingThermalPolicy.h
rename to media/module/libmediatranscoding/include/media/TranscodingThermalPolicy.h
diff --git a/media/libmediatranscoding/include/media/TranscodingUidPolicy.h b/media/module/libmediatranscoding/include/media/TranscodingUidPolicy.h
similarity index 100%
rename from media/libmediatranscoding/include/media/TranscodingUidPolicy.h
rename to media/module/libmediatranscoding/include/media/TranscodingUidPolicy.h
diff --git a/media/libmediatranscoding/include/media/UidPolicyInterface.h b/media/module/libmediatranscoding/include/media/UidPolicyInterface.h
similarity index 100%
rename from media/libmediatranscoding/include/media/UidPolicyInterface.h
rename to media/module/libmediatranscoding/include/media/UidPolicyInterface.h
diff --git a/media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp b/media/module/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
similarity index 100%
rename from media/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
rename to media/module/libmediatranscoding/tests/AdjustableMaxPriorityQueue_tests.cpp
diff --git a/media/libmediatranscoding/tests/Android.bp b/media/module/libmediatranscoding/tests/Android.bp
similarity index 100%
rename from media/libmediatranscoding/tests/Android.bp
rename to media/module/libmediatranscoding/tests/Android.bp
diff --git a/media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp b/media/module/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
similarity index 100%
rename from media/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
rename to media/module/libmediatranscoding/tests/TranscodingClientManager_tests.cpp
diff --git a/media/libmediatranscoding/tests/TranscodingLogger_tests.cpp b/media/module/libmediatranscoding/tests/TranscodingLogger_tests.cpp
similarity index 100%
rename from media/libmediatranscoding/tests/TranscodingLogger_tests.cpp
rename to media/module/libmediatranscoding/tests/TranscodingLogger_tests.cpp
diff --git a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp b/media/module/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
similarity index 99%
rename from media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
rename to media/module/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
index ef9c4f8..fdd327f 100644
--- a/media/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
+++ b/media/module/libmediatranscoding/tests/TranscodingSessionController_tests.cpp
@@ -337,6 +337,8 @@
         // Should have created new transcoder.
         EXPECT_EQ(mTranscoder->getGeneration(), generation);
         EXPECT_EQ(mTranscoder.use_count(), 2);
+        // b/240537336: Allow extra time to finish onError call
+        sleep(1);
     }
 
     void testPacerHelper(int numSubmits, int sessionDurationMs, int expectedSuccess) {
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/Video_4K_HEVC_10Frames_Audio.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/backyard_hevc_1920x1080_20Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/longtest_15s.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_12Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/plex_hevc_3840x2160_20Mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4 b/media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4
similarity index 100%
rename from media/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4
rename to media/module/libmediatranscoding/tests/assets/TranscodingTestAssets/video_1280x720_hevc_hdr10_static_3mbps.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/module/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
similarity index 100%
rename from media/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
rename to media/module/libmediatranscoding/tests/build_and_run_all_unit_tests.sh
diff --git a/media/libmediatranscoding/tests/push_assets.sh b/media/module/libmediatranscoding/tests/push_assets.sh
similarity index 100%
rename from media/libmediatranscoding/tests/push_assets.sh
rename to media/module/libmediatranscoding/tests/push_assets.sh
diff --git a/media/libmediatranscoding/transcoder/Android.bp b/media/module/libmediatranscoding/transcoder/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/Android.bp
rename to media/module/libmediatranscoding/transcoder/Android.bp
diff --git a/media/libmediatranscoding/transcoder/MediaSampleQueue.cpp b/media/module/libmediatranscoding/transcoder/MediaSampleQueue.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaSampleQueue.cpp
rename to media/module/libmediatranscoding/transcoder/MediaSampleQueue.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp b/media/module/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
rename to media/module/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp b/media/module/libmediatranscoding/transcoder/MediaSampleWriter.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
rename to media/module/libmediatranscoding/transcoder/MediaSampleWriter.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp b/media/module/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/module/libmediatranscoding/transcoder/MediaTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/MediaTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/MediaTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/NdkCommon.cpp b/media/module/libmediatranscoding/transcoder/NdkCommon.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/NdkCommon.cpp
rename to media/module/libmediatranscoding/transcoder/NdkCommon.cpp
diff --git a/media/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp b/media/module/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/module/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
rename to media/module/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
diff --git a/media/libmediatranscoding/transcoder/benchmark/Android.bp b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
similarity index 68%
rename from media/libmediatranscoding/transcoder/benchmark/Android.bp
rename to media/module/libmediatranscoding/transcoder/benchmark/Android.bp
index 459f0ae..f98b27d 100644
--- a/media/libmediatranscoding/transcoder/benchmark/Android.bp
+++ b/media/module/libmediatranscoding/transcoder/benchmark/Android.bp
@@ -26,16 +26,25 @@
     name: "MediaTranscoderBenchmark",
     srcs: ["MediaTranscoderBenchmark.cpp"],
     defaults: ["benchmarkdefaults"],
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
+    ],
 }
 
 cc_test {
     name: "MediaSampleReaderBenchmark",
     srcs: ["MediaSampleReaderBenchmark.cpp"],
     defaults: ["benchmarkdefaults"],
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
+    ],
 }
 
 cc_test {
     name: "MediaTrackTranscoderBenchmark",
     srcs: ["MediaTrackTranscoderBenchmark.cpp"],
     defaults: ["benchmarkdefaults"],
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libmediatranscoding/transcoder/benchmark/TranscodingBenchmark-1.2.zip?unzip=true",
+    ],
 }
diff --git a/media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml b/media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
rename to media/module/libmediatranscoding/transcoder/benchmark/AndroidTestTemplate.xml
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
rename to media/module/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
rename to media/module/libmediatranscoding/transcoder/benchmark/MediaTrackTranscoderBenchmark.cpp
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
rename to media/module/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSample.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSample.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSample.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSample.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleQueue.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleReader.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h b/media/module/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h b/media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaTrackTranscoderCallback.h
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/MediaTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/MediaTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/MediaTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h b/media/module/libmediatranscoding/transcoder/include/media/NdkCommon.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/NdkCommon.h
rename to media/module/libmediatranscoding/transcoder/include/media/NdkCommon.h
diff --git a/media/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/PassthroughTrackTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h b/media/module/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
rename to media/module/libmediatranscoding/transcoder/include/media/VideoTrackTranscoder.h
diff --git a/media/libmediatranscoding/transcoder/setloglevel.sh b/media/module/libmediatranscoding/transcoder/setloglevel.sh
similarity index 100%
rename from media/libmediatranscoding/transcoder/setloglevel.sh
rename to media/module/libmediatranscoding/transcoder/setloglevel.sh
diff --git a/media/libmediatranscoding/transcoder/tests/Android.bp b/media/module/libmediatranscoding/transcoder/tests/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/Android.bp
rename to media/module/libmediatranscoding/transcoder/tests/Android.bp
diff --git a/media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml b/media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
rename to media/module/libmediatranscoding/transcoder/tests/AndroidTestTemplate.xml
diff --git a/media/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp b/media/module/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/HdrTranscodeTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaSampleQueueTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/PassthroughTrackTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/README.md b/media/module/libmediatranscoding/transcoder/tests/README.md
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/README.md
rename to media/module/libmediatranscoding/transcoder/tests/README.md
diff --git a/media/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h b/media/module/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h
rename to media/module/libmediatranscoding/transcoder/tests/TranscoderTestUtils.h
diff --git a/media/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp b/media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
rename to media/module/libmediatranscoding/transcoder/tests/VideoTrackTranscoderTests.cpp
diff --git a/media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh b/media/module/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
rename to media/module/libmediatranscoding/transcoder/tests/build_and_run_all_unit_tests.sh
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp b/media/module/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
rename to media/module/libmediatranscoding/transcoder/tests/fuzzer/Android.bp
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/README.md b/media/module/libmediatranscoding/transcoder/tests/fuzzer/README.md
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/fuzzer/README.md
rename to media/module/libmediatranscoding/transcoder/tests/fuzzer/README.md
diff --git a/media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp b/media/module/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
rename to media/module/libmediatranscoding/transcoder/tests/fuzzer/media_transcoder_fuzzer.cpp
diff --git a/media/libmediatranscoding/transcoder/tools/Android.bp b/media/module/libmediatranscoding/transcoder/tools/Android.bp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tools/Android.bp
rename to media/module/libmediatranscoding/transcoder/tools/Android.bp
diff --git a/media/libmediatranscoding/transcoder/tools/Transcode.cpp b/media/module/libmediatranscoding/transcoder/tools/Transcode.cpp
similarity index 100%
rename from media/libmediatranscoding/transcoder/tools/Transcode.cpp
rename to media/module/libmediatranscoding/transcoder/tools/Transcode.cpp
diff --git a/media/libwatchdog/Android.bp b/media/module/libwatchdog/Android.bp
similarity index 100%
rename from media/libwatchdog/Android.bp
rename to media/module/libwatchdog/Android.bp
diff --git a/media/libwatchdog/Watchdog.cpp b/media/module/libwatchdog/Watchdog.cpp
similarity index 100%
rename from media/libwatchdog/Watchdog.cpp
rename to media/module/libwatchdog/Watchdog.cpp
diff --git a/media/libwatchdog/include/watchdog/Watchdog.h b/media/module/libwatchdog/include/watchdog/Watchdog.h
similarity index 100%
rename from media/libwatchdog/include/watchdog/Watchdog.h
rename to media/module/libwatchdog/include/watchdog/Watchdog.h
diff --git a/media/module/metadatautils/Android.bp b/media/module/metadatautils/Android.bp
new file mode 100644
index 0000000..c77474f
--- /dev/null
+++ b/media/module/metadatautils/Android.bp
@@ -0,0 +1,46 @@
+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"],
+}
+
+cc_library_static {
+    name: "libstagefright_metadatautils",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media",
+    ],
+    min_sdk_version: "29",
+
+    srcs: ["MetaDataUtils.cpp"],
+
+    cflags: [
+        "-Werror",
+        "-Wall",
+    ],
+    sanitize: {
+        misc_undefined: [
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+
+    header_libs: [
+        "libaudioclient_headers",
+        "libstagefright_headers",
+        "libstagefright_foundation_headers",
+        "media_ndk_headers",
+    ],
+
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
+    export_include_dirs: ["include"],
+}
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/module/metadatautils/MetaDataUtils.cpp
similarity index 100%
rename from media/libstagefright/MetaDataUtils.cpp
rename to media/module/metadatautils/MetaDataUtils.cpp
diff --git a/media/module/metadatautils/TEST_MAPPING b/media/module/metadatautils/TEST_MAPPING
new file mode 100644
index 0000000..21836a5
--- /dev/null
+++ b/media/module/metadatautils/TEST_MAPPING
@@ -0,0 +1,9 @@
+// mappings for frameworks/av/media/module/metadatautils
+{
+  // tests which require dynamic content
+  // invoke with: atest -- --enable-module-dynamic-download=true
+  // TODO(b/148094059): unit tests not allowed to download content
+  "dynamic-presubmit": [
+    { "name": "MetaDataUtilsTest" }
+  ]
+}
diff --git a/media/libstagefright/include/media/stagefright/MetaDataUtils.h b/media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
similarity index 100%
rename from media/libstagefright/include/media/stagefright/MetaDataUtils.h
rename to media/module/metadatautils/include/media/stagefright/MetaDataUtils.h
diff --git a/media/libstagefright/tests/metadatautils/Android.bp b/media/module/metadatautils/test/Android.bp
similarity index 93%
rename from media/libstagefright/tests/metadatautils/Android.bp
rename to media/module/metadatautils/test/Android.bp
index ecdf89b..21f38f6 100644
--- a/media/libstagefright/tests/metadatautils/Android.bp
+++ b/media/module/metadatautils/test/Android.bp
@@ -20,9 +20,6 @@
     // all of the 'license_kinds' from "frameworks_av_media_libstagefright_tests_license"
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: [
-        "frameworks_av_media_libstagefright_tests_license",
-    ],
 }
 
 cc_test {
diff --git a/media/libstagefright/tests/metadatautils/AndroidTest.xml b/media/module/metadatautils/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/tests/metadatautils/AndroidTest.xml
rename to media/module/metadatautils/test/AndroidTest.xml
diff --git a/media/libstagefright/tests/metadatautils/MetaDataUtilsTest.cpp b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
similarity index 96%
rename from media/libstagefright/tests/metadatautils/MetaDataUtilsTest.cpp
rename to media/module/metadatautils/test/MetaDataUtilsTest.cpp
index 9fd5fdb..7c35249 100644
--- a/media/libstagefright/tests/metadatautils/MetaDataUtilsTest.cpp
+++ b/media/module/metadatautils/test/MetaDataUtilsTest.cpp
@@ -19,9 +19,10 @@
 #include <utils/Log.h>
 
 #include <fstream>
+#include <memory>
 #include <string>
 
-#include <ESDS.h>
+#include <media/esds/ESDS.h>
 #include <media/NdkMediaFormat.h>
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaDefs.h>
@@ -228,7 +229,7 @@
     ASSERT_TRUE(status) << "Failed to get the mime type";
     ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_VIDEO_AVC);
 
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
 
     status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -264,7 +265,6 @@
     int32_t result = memcmp(csdAMediaFormatBuffer, csdMetaDataBaseBuffer, csdAMediaFormatSize);
     ASSERT_EQ(result, 0) << "CSD from AMediaFormat and MetaDataBase do not match";
 
-    delete metaData;
     AMediaFormat_delete(csdData);
 }
 
@@ -275,7 +275,7 @@
     bool status = MakeAVCCodecSpecificData(csdData, mInputBuffer, mInputBufferSize);
     ASSERT_FALSE(status) << "MakeAVCCodecSpecificData with AMediaFormat succeeds with invalid data";
 
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
 
     status = MakeAVCCodecSpecificData(*metaData, mInputBuffer, mInputBufferSize);
@@ -307,7 +307,7 @@
     ASSERT_TRUE(status) << "Failed to get the mime type";
     ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
 
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create MetaData Base";
 
     status = MakeAACCodecSpecificData(*metaData, mAacProfile, mAacSamplingFreqIndex,
@@ -356,11 +356,10 @@
     ASSERT_EQ(memcmpResult, 0) << "AMediaFormat and MetaDataBase CSDs do not match";
 
     AMediaFormat_delete(csdData);
-    delete metaData;
 }
 
 TEST_P(AacADTSTest, AacADTSValidationTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -380,12 +379,10 @@
     status = metaData->findCString(kKeyMIMEType, &mimeType);
     ASSERT_TRUE(status) << "Failed to get mime type";
     ASSERT_STREQ(mimeType, MEDIA_MIMETYPE_AUDIO_AAC);
-
-    delete metaData;
 }
 
 TEST_P(AacCSDValidateTest, AacInvalidInputTest) {
-    MetaDataBase *metaData = new MetaDataBase();
+    std::unique_ptr<MetaDataBase> metaData(new MetaDataBase());
     ASSERT_NE(metaData, nullptr) << "Failed to create meta data";
 
     bool status = MakeAACCodecSpecificData(*metaData, mInputBuffer, kAdtsCsdSize);
@@ -412,14 +409,14 @@
         istringstream dataStringLine(dataLine);
         dataStringLine >> comment;
 
-        char *buffer = strndup(comment.c_str(), commentLength);
+        std::unique_ptr<char[]> buffer(new char[commentLength]);
         ASSERT_NE(buffer, nullptr) << "Failed to allocate buffer of size: " << commentLength;
+        strncpy(buffer.get(), comment.c_str(), commentLength);
 
         AMediaFormat *fileMeta = AMediaFormat_new();
         ASSERT_NE(fileMeta, nullptr) << "Failed to create AMedia format";
 
-        parseVorbisComment(fileMeta, buffer, commentLength);
-        free(buffer);
+        parseVorbisComment(fileMeta, buffer.get(), commentLength);
 
         if (!strncasecmp(tag.c_str(), "ANDROID_HAPTIC", sizeof(tag))) {
             int32_t numChannelExpected = stoi(value);
diff --git a/media/libstagefright/tests/metadatautils/MetaDataUtilsTestEnvironment.h b/media/module/metadatautils/test/MetaDataUtilsTestEnvironment.h
similarity index 100%
rename from media/libstagefright/tests/metadatautils/MetaDataUtilsTestEnvironment.h
rename to media/module/metadatautils/test/MetaDataUtilsTestEnvironment.h
diff --git a/media/libstagefright/tests/metadatautils/README.md b/media/module/metadatautils/test/README.md
similarity index 100%
rename from media/libstagefright/tests/metadatautils/README.md
rename to media/module/metadatautils/test/README.md
diff --git a/services/minijail/Android.bp b/media/module/minijail/Android.bp
similarity index 100%
rename from services/minijail/Android.bp
rename to media/module/minijail/Android.bp
diff --git a/services/minijail/OWNERS b/media/module/minijail/OWNERS
similarity index 100%
rename from services/minijail/OWNERS
rename to media/module/minijail/OWNERS
diff --git a/services/minijail/TEST_MAPPING b/media/module/minijail/TEST_MAPPING
similarity index 100%
rename from services/minijail/TEST_MAPPING
rename to media/module/minijail/TEST_MAPPING
diff --git a/services/minijail/av_services_minijail_unittest.cpp b/media/module/minijail/av_services_minijail_unittest.cpp
similarity index 100%
rename from services/minijail/av_services_minijail_unittest.cpp
rename to media/module/minijail/av_services_minijail_unittest.cpp
diff --git a/services/minijail/minijail.cpp b/media/module/minijail/minijail.cpp
similarity index 100%
rename from services/minijail/minijail.cpp
rename to media/module/minijail/minijail.cpp
diff --git a/services/minijail/minijail.h b/media/module/minijail/minijail.h
similarity index 100%
rename from services/minijail/minijail.h
rename to media/module/minijail/minijail.h
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/module/mpeg2ts/ATSParser.cpp
similarity index 97%
rename from media/libstagefright/mpeg2ts/ATSParser.cpp
rename to media/module/mpeg2ts/ATSParser.cpp
index 1482072..6aeea3b 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/module/mpeg2ts/ATSParser.cpp
@@ -556,7 +556,15 @@
             if (descriptor_length > ES_info_length) {
                 return ERROR_MALFORMED;
             }
-            if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
+
+            // The DTS descriptor is used in the PSI PMT to identify streams which carry
+            // DTS audio(core only). If a DTS descriptor is present, a DTS-HD or DTS-UHD
+            // descriptors shall not be present in the same ES_info descriptor loop.
+            if (descriptor_tag == DESCRIPTOR_DTS) {
+                info.mType = STREAMTYPE_DTS;
+                ES_info_length -= descriptor_length;
+                br->skipBits(descriptor_length * 8);
+            } else if (descriptor_tag == DESCRIPTOR_CA && descriptor_length >= 4) {
                 hasStreamCA = true;
                 streamCA.mSystemID = br->getBits(16);
                 streamCA.mPID = br->getBits(16) & 0x1fff;
@@ -575,6 +583,16 @@
                 if (descTagExt == EXT_DESCRIPTOR_DVB_AC4) {
                     info.mTypeExt = EXT_DESCRIPTOR_DVB_AC4;
                     br->skipBits(descriptor_length * 8);
+                } else if (descTagExt == EXT_DESCRIPTOR_DVB_DTS_HD) {
+                    // DTS HD extended descriptor which can accommodate core only formats
+                    // as well as extension only and core + extension combinations.
+                    info.mTypeExt = EXT_DESCRIPTOR_DVB_DTS_HD;
+                    br->skipBits(descriptor_length * 8);
+                } else if (descTagExt == EXT_DESCRIPTOR_DVB_DTS_UHD) {
+                    // The DTS-UHD descriptor is used in the PSI PMT to identify streams
+                    // which carry DTS-UHD audio
+                    info.mTypeExt = EXT_DESCRIPTOR_DVB_DTS_UHD;
+                    br->skipBits(descriptor_length * 8);
                 } else if (descTagExt == EXT_DESCRIPTOR_DVB_AUDIO_PRESELECTION &&
                            descriptor_length >= 1) {
                     // DVB BlueBook A038 Table 110
@@ -920,9 +938,17 @@
             mode = ElementaryStreamQueue::EAC3;
             break;
 
+        case STREAMTYPE_DTS:
+            mode = ElementaryStreamQueue::DTS;
+            break;
+
         case STREAMTYPE_PES_PRIVATE_DATA:
             if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4) {
                 mode = ElementaryStreamQueue::AC4;
+            } else if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_HD) {
+                mode = ElementaryStreamQueue::DTS_HD;
+            } else if (mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_UHD) {
+                mode = ElementaryStreamQueue::DTS_UHD;
             }
             break;
 
@@ -1158,9 +1184,12 @@
         case STREAMTYPE_EAC3:
         case STREAMTYPE_AAC_ENCRYPTED:
         case STREAMTYPE_AC3_ENCRYPTED:
+        case STREAMTYPE_DTS:
             return true;
         case STREAMTYPE_PES_PRIVATE_DATA:
-            return mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4;
+            return (mStreamTypeExt == EXT_DESCRIPTOR_DVB_AC4
+                    || mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_HD
+                    || mStreamTypeExt == EXT_DESCRIPTOR_DVB_DTS_UHD);
 
         default:
             return false;
diff --git a/media/libstagefright/mpeg2ts/Android.bp b/media/module/mpeg2ts/Android.bp
similarity index 98%
rename from media/libstagefright/mpeg2ts/Android.bp
rename to media/module/mpeg2ts/Android.bp
index 283df1e..bf762c6 100644
--- a/media/libstagefright/mpeg2ts/Android.bp
+++ b/media/module/mpeg2ts/Android.bp
@@ -51,6 +51,7 @@
         "libmedia_datasource_headers",
         "libaudioclient_headers",
         "media_ndk_headers",
+        "libstagefright_headers",
         "libstagefright_foundation_headers",
     ],
 
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/module/mpeg2ts/AnotherPacketSource.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
rename to media/module/mpeg2ts/AnotherPacketSource.cpp
diff --git a/media/libstagefright/mpeg2ts/CasManager.cpp b/media/module/mpeg2ts/CasManager.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/CasManager.cpp
rename to media/module/mpeg2ts/CasManager.cpp
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/module/mpeg2ts/ESQueue.cpp
similarity index 75%
rename from media/libstagefright/mpeg2ts/ESQueue.cpp
rename to media/module/mpeg2ts/ESQueue.cpp
index 192ba77..2dc7b0a 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/module/mpeg2ts/ESQueue.cpp
@@ -362,6 +362,436 @@
     return OK;
 }
 
+#define RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitstream, size) \
+    do { \
+        if ((bitstream).numBitsLeft() < (size)) { \
+        ALOGE("Not enough bits left for further parsing"); \
+        return ERROR_MALFORMED; } \
+    } while (0)
+
+// Parse DTS Digital Surround and DTS Express(LBR) stream header
+static status_t parseDTSHDSyncFrame(
+    const uint8_t *ptr, size_t size, unsigned &frameSize, sp<MetaData> *metaData) {
+    static const unsigned channelCountTable[] = {1, 2, 2, 2, 2, 3, 3, 4,
+                                                 4, 5, 6, 6, 6, 7, 8, 8};
+    static const unsigned samplingRateTableCoreSS[] = {0, 8000, 16000, 32000, 0, 0, 11025, 22050,
+                                                       44100, 0, 0, 12000, 24000, 48000, 0, 0};
+    static const unsigned samplingRateTableExtSS[] = {8000, 16000, 32000, 64000, 128000,
+                                                      22050, 44100, 88200, 176400, 352800,
+                                                      12000, 24000, 48000, 96000, 192000, 384000};
+
+    const uint32_t DTSHD_SYNC_CORE_16BIT_BE = 0x7ffe8001;
+    const uint32_t DTSHD_SYNC_EXSS_16BIT_BE = 0x64582025;
+
+    uint32_t numChannels = 0, samplingRate = 0;
+    bool isLBR = false;
+
+    ABitReader bits(ptr, size);
+
+    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 32);
+    uint32_t dtshdSyncWord = bits.getBits(32);
+
+    // Expecting DTS Digital Surround or DTS Express(LBR) streams only
+    if (dtshdSyncWord == DTSHD_SYNC_CORE_16BIT_BE) { // DTS Digital Surround Header
+        RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (1 + 5 + 1 + 7 + 14 + 6 + 4 + 15 + 2));
+
+        // FTYPE, SHORT, CRC, NBLKS
+        bits.skipBits(1 + 5 + 1 + 7);
+
+        frameSize = bits.getBits(14) + 1;
+        uint32_t amode = bits.getBits(6);
+        uint32_t freqIndex = bits.getBits(4);
+
+        // RATE, FIXEDBIT, DYNF, TIMEF, AUXF, HDCD, EXT_AUDIO_ID, EXT_AUDIO, ASPF
+        bits.skipBits(5 + 1 + 1 + 1 + 1 + 1 + 3 + 1 + 1);
+
+        uint32_t lfeFlag = bits.getBits(2);
+        numChannels = (amode <= 15) ? channelCountTable[amode] : 0;
+        numChannels += ((lfeFlag == 1) || (lfeFlag == 2)) ? 1 : 0;
+        samplingRate = (freqIndex <= 15) ? samplingRateTableCoreSS[freqIndex] : 0;
+
+        isLBR = false;
+    } else if (dtshdSyncWord == DTSHD_SYNC_EXSS_16BIT_BE) { // DTS Express(LBR) Header
+        RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (8 + 2 + 1));
+
+        uint32_t extHeadersize, extSSFsize;
+        uint32_t numAudioPresent = 1, numAssets = 1;
+        uint32_t nuActiveExSSMask[8];
+
+        // userDefinedBits
+        bits.skipBits(8);
+
+        uint32_t extSSIndex = bits.getBits(2);
+        uint32_t headerSizeType = bits.getBits(1);
+
+        if (headerSizeType == 0) {
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (8 + 16));
+
+            extHeadersize = bits.getBits(8) + 1;
+            extSSFsize = bits.getBits(16) + 1;
+        } else {
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (12 + 20));
+
+            extHeadersize = bits.getBits(12) + 1;
+            extSSFsize = bits.getBits(20) + 1;
+        }
+
+        RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (1));
+
+        uint32_t staticFieldsPresent = bits.getBits(1);
+
+        if (staticFieldsPresent) {
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (2 + 3 + 1));
+
+            // nuRefClockCode, nuExSSFrameDurationCode
+            bits.skipBits(2 + 3);
+
+            if (bits.getBits(1)) {
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (32 + 4));
+
+                bits.skipBits(32 + 4);
+            }
+
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (3 + 3));
+
+            // numAudioPresent, numAssets
+            bits.skipBits(3 + 3);
+
+            for (uint32_t nAuPr = 0; nAuPr < numAudioPresent; nAuPr++) {
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (extSSIndex + 1));
+
+                nuActiveExSSMask[nAuPr] = bits.getBits(extSSIndex + 1);
+            }
+
+            for (uint32_t nAuPr = 0; nAuPr < numAudioPresent; nAuPr++) {
+                for (uint32_t nSS = 0; nSS < extSSIndex + 1; nSS++) {
+                    if (((nuActiveExSSMask[nAuPr] >> nSS) & 0x1) == 1) {
+                        RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 8);
+
+                        // nuActiveAssetMask
+                        bits.skipBits(8);
+                    }
+                }
+            }
+
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+            // bMixMetadataEnbl
+            if (bits.getBits(1)) {
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (2 + 2 + 2));
+
+                // nuMixMetadataAdjLevel
+                bits.skipBits(2);
+
+                uint32_t bits4MixOutMask = (bits.getBits(2) + 1) << 2;
+                uint32_t numMixOutConfigs = bits.getBits(2) + 1;
+
+                for (int ns = 0; ns < numMixOutConfigs; ns++) {
+                    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, bits4MixOutMask);
+
+                    // nuMixOutChMask
+                    bits.skipBits(bits4MixOutMask);
+                }
+            }
+        }
+
+        for (int nAst = 0; nAst < numAssets; nAst++) {
+            int bits4ExSSFsize = (headerSizeType == 0) ? 16 : 20;
+
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, bits4ExSSFsize);
+
+            bits.skipBits(bits4ExSSFsize);
+        }
+
+        /* Asset descriptor */
+        for (int nAst = 0; nAst < numAssets; nAst++) {
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (9 + 3));
+
+            // nuAssetDescriptFsize, nuAssetIndex
+            bits.skipBits(9 + 3);
+
+            if (staticFieldsPresent) {
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+                // bAssetTypeDescrPresent
+                if (bits.getBits(1)) {
+                    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 4);
+
+                    // nuAssetTypeDescriptor
+                    bits.skipBits(4);
+                }
+
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+                // bLanguageDescrPresent
+                if (bits.getBits(1)) {
+                    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 24);
+
+                    // LanguageDescriptor
+                    bits.skipBits(24);
+                }
+
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 1);
+
+                // bInfoTextPresent
+                if (bits.getBits(1)) {
+                    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 10);
+
+                    uint32_t nuInfoTextByteSize = bits.getBits(10) + 1;
+
+                    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (nuInfoTextByteSize * 8));
+
+                    // InfoTextString
+                    bits.skipBits(nuInfoTextByteSize * 8);
+                }
+
+                RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (5 + 4 + 8));
+
+                // nuBitResolution
+                bits.skipBits(5);
+
+                samplingRate = samplingRateTableExtSS[bits.getBits(4)];
+                numChannels = bits.getBits(8) + 1;
+            }
+        }
+
+        frameSize = extHeadersize + extSSFsize;
+        isLBR = true;
+    } else {
+        ALOGE("No valid sync word in DTS/DTSHD header");
+        return ERROR_MALFORMED;
+    }
+
+    if (metaData != NULL) {
+        if (isLBR) {
+            (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS_HD);
+            (*metaData)->setInt32(kKeyAudioProfile, 0x2); // CodecProfileLevel.DTS_HDProfileLBR
+        } else {
+            (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS);
+        }
+        (*metaData)->setInt32(kKeyChannelCount, numChannels);
+        (*metaData)->setInt32(kKeySampleRate, samplingRate);
+    }
+    return OK;
+}
+
+static status_t extractVarLenBitFields(
+    ABitReader *bits, size_t *bitsUsed, uint32_t *value,
+    unsigned ucTable[], bool extractAndAddFlag) {
+
+    static const unsigned bitsUsedTbl[8] = {1, 1, 1, 1, 2, 2, 3, 3}; // prefix code lengths
+    static const unsigned indexTbl[8] = {0, 0, 0, 0, 1, 1, 2, 3}; // code to prefix code index map
+
+    /* Clone the bitstream */
+    ABitReader bitStream(bits->data(), bits->numBitsLeft() / 8);
+    ABitReader bitstreamClone(bits->data(), bits->numBitsLeft() / 8);
+
+    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitstreamClone, 3);
+
+    unsigned code = bitstreamClone.getBits(3);
+    unsigned totalBitsUsed = bitsUsedTbl[code];
+    unsigned unIndex = indexTbl[code];
+
+    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitStream, totalBitsUsed);
+
+    bitStream.skipBits(totalBitsUsed);
+
+    uint32_t unValue = 0;
+    if (ucTable[unIndex] > 0) {
+        if (extractAndAddFlag) {
+            for (unsigned un = 0; un < unIndex; un++) {
+                unValue += (1 << ucTable[un]);
+            }
+
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitStream, ucTable[unIndex]);
+
+            unValue += bitStream.getBits(ucTable[unIndex]);
+            totalBitsUsed += ucTable[unIndex];
+        } else {
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bitStream, ucTable[unIndex]);
+
+            unValue += bitStream.getBits(ucTable[unIndex]);
+            totalBitsUsed += ucTable[unIndex];
+        }
+    }
+
+    *bitsUsed = (size_t)totalBitsUsed;
+    *value = unValue;
+    return OK;
+}
+
+// Parse DTS UHD Profile-2 stream header
+static status_t parseDTSUHDSyncFrame(
+    const uint8_t *ptr, size_t size, unsigned &frameSize, sp<MetaData> *metaData) {
+
+    static const uint32_t DTSUHD_SYNC_CORE_16BIT_BE = 0x40411BF2;
+    static const uint32_t DTSUHD_NONSYNC_CORE_16BIT_BE = 0x71C442E8;
+
+    unsigned audioSamplRate = 0;
+
+    ABitReader bits(ptr, size);
+
+    RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 32);
+
+    uint32_t syncWord = bits.getBits(32);
+
+    bool isSyncFrameFlag = false;
+    switch (syncWord) {
+        case DTSUHD_SYNC_CORE_16BIT_BE:
+            isSyncFrameFlag = true;
+            break;
+        case DTSUHD_NONSYNC_CORE_16BIT_BE:
+            isSyncFrameFlag = false;
+            break;
+        default:
+            ALOGE("No valid sync word in DTSUHD header");
+            return ERROR_MALFORMED; // invalid sync word
+    }
+
+    unsigned uctable1[4] = { 5, 8, 10, 12 };
+    uint32_t sizeOfFTOCPayload = 0;
+    size_t nuBitsUsed = 0;
+    status_t status = OK;
+
+    status = extractVarLenBitFields(&bits, &nuBitsUsed, &sizeOfFTOCPayload, uctable1, true);
+
+    if (status != OK) {
+        ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+        return ERROR_MALFORMED;
+    }
+
+    bits.skipBits(nuBitsUsed);
+
+    if (isSyncFrameFlag) {
+        RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (1 + 2 + 3 + 2 + 1));
+
+        // FullChannelBasedMixFlag, ETSI TS 103 491 V1.2.1, Section 6.4.6.1
+        if (!(bits.getBits(1))) {
+            // This implementation only supports full channel mask-based
+            // audio presentation (i.e. 2.0, 5.1, 11.1 mix without objects)
+            ALOGE("Objects not supported, only DTSUHD full channel mask-based mix");
+            return ERROR_MALFORMED;
+        }
+
+        // BaseDuration, FrameDuration
+        bits.skipBits(2 + 3);
+
+        unsigned clockRateIndex = bits.getBits(2);
+        unsigned clockRateHertz = 0;
+
+        switch (clockRateIndex) {
+            case 0:
+                clockRateHertz = 32000;
+                break;
+            case 1:
+                clockRateHertz = 44100;
+                break;
+            case 2:
+                clockRateHertz = 48000;
+                break;
+            default:
+                ALOGE("Invalid clockRateIndex in DTSUHD header");
+                return ERROR_MALFORMED;
+        }
+
+        if (bits.getBits(1)) {
+            RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, (32 + 4));
+
+            bits.skipBits(32 + 4);
+        }
+
+        RETURN_ERROR_IF_NOT_ENOUGH_BYTES_LEFT(bits, 2);
+
+        unsigned samplRateMultiplier = (1 << bits.getBits(2));
+        audioSamplRate = clockRateHertz * samplRateMultiplier;
+    }
+
+    uint32_t chunkPayloadBytes = 0;
+    int numOfMDChunks = isSyncFrameFlag ? 1 : 0; // Metadata chunks
+    for (int nmdc = 0; nmdc < numOfMDChunks; nmdc++) {
+        unsigned uctable2[4] = {6, 9, 12, 15};
+        uint32_t nuMDChunkSize = 0;
+        nuBitsUsed = 0;
+
+        status = extractVarLenBitFields(&bits, &nuBitsUsed, &nuMDChunkSize, uctable2, true);
+        if (status != OK) {
+            ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+            return ERROR_MALFORMED;
+        }
+
+        bits.skipBits(nuBitsUsed);
+
+        if (nuMDChunkSize > 32767) {
+            ALOGE("Unsupported number of metadata chunks in DTSUHD header");
+            return ERROR_MALFORMED;
+        }
+        chunkPayloadBytes += nuMDChunkSize;
+    }
+
+    // Ony one audio chunk is supported
+    int numAudioChunks = 1;
+    for (int nac = 0; nac < numAudioChunks; nac++) {
+        uint32_t acID = 256, nuAudioChunkSize = 0;
+
+        // isSyncFrameFlag means that ACID is present
+        if (isSyncFrameFlag) {
+            unsigned uctable3[4] = {2, 4, 6, 8};
+            nuBitsUsed = 0;
+
+            status = extractVarLenBitFields(&bits, &nuBitsUsed, &acID, uctable3, true);
+
+            if (status != OK) {
+                ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+                return ERROR_MALFORMED;
+            }
+
+            bits.skipBits(nuBitsUsed);
+        }
+
+        nuBitsUsed = 0;
+        if (acID == 0) {
+            nuAudioChunkSize = 0;
+        } else {
+            unsigned uctable4[4] = {9, 11, 13, 16};
+
+            status = extractVarLenBitFields(&bits, &nuBitsUsed, &nuAudioChunkSize, uctable4, true);
+
+            if (status != OK) {
+                ALOGE("Failed to extractVarLenBitFields from DTSUHD header");
+                return ERROR_MALFORMED;
+            }
+        }
+
+        if (nuAudioChunkSize > 65535){
+            ALOGE("Unsupported number of audio chunks in DTSUHD header");
+            return ERROR_MALFORMED;
+        }
+
+        chunkPayloadBytes += nuAudioChunkSize;
+    }
+
+    frameSize = (sizeOfFTOCPayload + 1) + chunkPayloadBytes;
+
+    if (metaData != NULL) {
+        (*metaData)->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_DTS_UHD);
+        (*metaData)->setInt32(kKeyAudioProfile, 0x2); // CodecProfileLevel.DTS_UHDProfileP2
+        (*metaData)->setInt32(kKeyChannelCount, 2); // Setting default channel count as stereo
+        (*metaData)->setInt32(kKeySampleRate, audioSamplRate);
+    }
+
+    return OK;
+}
+
+static status_t isSeeminglyValidDTSHDHeader(const uint8_t *ptr, size_t size,unsigned &frameSize)
+{
+    return parseDTSHDSyncFrame(ptr, size, frameSize, NULL);
+}
+
+static status_t isSeeminglyValidDTSUHDHeader(const uint8_t *ptr, size_t size,unsigned &frameSize)
+{
+    return parseDTSUHDSyncFrame(ptr, size, frameSize, NULL);
+}
+
 static status_t IsSeeminglyValidAC4Header(const uint8_t *ptr, size_t size, unsigned &frameSize) {
     return parseAC4SyncFrame(ptr, size, frameSize, NULL);
 }
@@ -655,6 +1085,70 @@
                 break;
             }
 
+            case DTS: //  Checking for DTS or DTS-HD syncword
+            case DTS_HD:
+            {
+                uint8_t *ptr = (uint8_t *)data;
+                unsigned frameSize = 0;
+                ssize_t startOffset = -1;
+
+                for (size_t i = 0; i < size; ++i) {
+                    if (isSeeminglyValidDTSHDHeader(&ptr[i], size - i, frameSize) == OK) {
+                        startOffset = i;
+                        break;
+                    }
+                }
+
+                if (startOffset < 0) {
+                    return ERROR_MALFORMED;
+                }
+                if (startOffset > 0) {
+                    ALOGI("found something resembling a DTS-HD syncword at "
+                          "offset %zd",
+                          startOffset);
+                }
+
+                if (frameSize != size - startOffset) {
+                    ALOGV("DTS-HD frame size is %u bytes, while the buffer size is %zd bytes.",
+                          frameSize, size - startOffset);
+                }
+
+                data = &ptr[startOffset];
+                size -= startOffset;
+                break;
+            }
+
+            case DTS_UHD:
+            {
+                uint8_t *ptr = (uint8_t *)data;
+                ssize_t startOffset = -1;
+                unsigned frameSize = 0;
+
+                for (size_t i = 0; i < size; ++i) {
+                    if (isSeeminglyValidDTSUHDHeader(&ptr[i], size - i, frameSize) == OK) {
+                        startOffset = i;
+                        break;
+                    }
+                }
+
+                if (startOffset < 0) {
+                    return ERROR_MALFORMED;
+                }
+                if (startOffset >= 0) {
+                    ALOGI("found something resembling a DTS UHD syncword"
+                          "syncword at offset %zd",
+                          startOffset);
+                }
+
+                if (frameSize != size - startOffset) {
+                    ALOGV("DTS-UHD frame size is %u bytes, while the buffer size is %zd bytes.",
+                          frameSize, size - startOffset);
+                }
+                data = &ptr[startOffset];
+                size -= startOffset;
+                break;
+            }
+
             case PCM_AUDIO:
             case METADATA:
             {
@@ -928,6 +1422,11 @@
             return dequeueAccessUnitPCMAudio();
         case METADATA:
             return dequeueAccessUnitMetadata();
+        case DTS: // Using same dequeue function for both DTS and DTS-HD types.
+        case DTS_HD:
+            return dequeueAccessUnitDTSOrDTSHD();
+        case DTS_UHD:
+            return dequeueAccessUnitDTSUHD();
         default:
             if (mMode != MPEG_AUDIO) {
                 ALOGE("Unknown mode");
@@ -937,6 +1436,113 @@
     }
 }
 
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitDTSOrDTSHD() {
+    unsigned syncStartPos = 0; // in bytes
+    unsigned payloadSize = 0;
+    sp<MetaData> format = new MetaData;
+
+    ALOGV("dequeueAccessUnitDTSOrDTSHD[%d]: mBuffer %p(%zu)", mAUIndex,
+          mBuffer->data(), mBuffer->size());
+
+    while (true) {
+        if (syncStartPos + 4 >= mBuffer->size()) {
+            return NULL;
+        }
+        uint8_t *ptr = mBuffer->data() + syncStartPos;
+        size_t size = mBuffer->size() - syncStartPos;
+        status_t status = parseDTSHDSyncFrame(ptr, size, payloadSize, &format);
+        if (status == 0) {
+            break;
+        }
+        ++syncStartPos;
+    }
+
+    if (mBuffer->size() < syncStartPos + payloadSize) {
+        ALOGV("Not enough buffer size for DTS/DTS-HD");
+        return NULL;
+    }
+
+    if (mFormat == NULL) {
+        mFormat = format;
+    }
+
+    int64_t timeUs = fetchTimestamp(syncStartPos + payloadSize);
+    if (timeUs < 0LL) {
+        ALOGE("negative timeUs");
+        return NULL;
+    }
+    mAUIndex++;
+
+    sp<ABuffer> accessUnit = new ABuffer(syncStartPos + payloadSize);
+    memcpy(accessUnit->data(), mBuffer->data(), syncStartPos + payloadSize);
+
+    accessUnit->meta()->setInt64("timeUs", timeUs);
+    accessUnit->meta()->setInt32("isSync", 1);
+
+    memmove(
+        mBuffer->data(),
+        mBuffer->data() + syncStartPos + payloadSize,
+        mBuffer->size() - syncStartPos - payloadSize);
+
+    mBuffer->setRange(0, mBuffer->size() - syncStartPos - payloadSize);
+
+    return accessUnit;
+}
+
+sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitDTSUHD()
+{
+    unsigned syncStartPos = 0; // in bytes
+    unsigned payloadSize = 0;
+    sp<MetaData> format = new MetaData;
+
+    ALOGV("dequeueAccessUnitDTSUHD[%d]: mBuffer %p(%zu)", mAUIndex,
+          mBuffer->data(), mBuffer->size());
+
+    while (true) {
+        if (syncStartPos + 4 >= mBuffer->size()) {
+            return NULL;
+        }
+        uint8_t *ptr = mBuffer->data() + syncStartPos;
+        size_t size = mBuffer->size() - syncStartPos;
+        status_t status = parseDTSUHDSyncFrame(ptr, size, payloadSize, &format);
+        if (status == 0) {
+            break;
+        }
+        ++syncStartPos;
+    }
+
+    if (mBuffer->size() < syncStartPos + payloadSize) {
+        ALOGV("Not enough buffer size for DTS-UHD");
+        return NULL;
+    }
+
+    if (mFormat == NULL) {
+        mFormat = format;
+    }
+
+    int64_t timeUs = fetchTimestamp(syncStartPos + payloadSize);
+    if (timeUs < 0LL) {
+        ALOGE("negative timeUs");
+        return NULL;
+    }
+    mAUIndex++;
+
+    sp<ABuffer> accessUnit = new ABuffer(syncStartPos + payloadSize);
+    memcpy(accessUnit->data(), mBuffer->data(), syncStartPos + payloadSize);
+
+    accessUnit->meta()->setInt64("timeUs", timeUs);
+    accessUnit->meta()->setInt32("isSync", 1);
+
+    memmove(
+        mBuffer->data(),
+        mBuffer->data() + syncStartPos + payloadSize,
+        mBuffer->size() - syncStartPos - payloadSize);
+
+    mBuffer->setRange(0, mBuffer->size() - syncStartPos - payloadSize);
+
+    return accessUnit;
+}
+
 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitEAC3() {
     unsigned syncStartPos = 0;  // in bytes
     unsigned payloadSize = 0;
diff --git a/media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp b/media/module/mpeg2ts/HlsSampleDecryptor.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/HlsSampleDecryptor.cpp
rename to media/module/mpeg2ts/HlsSampleDecryptor.cpp
diff --git a/media/libstagefright/mpeg2ts/MODULE_LICENSE_APACHE2 b/media/module/mpeg2ts/MODULE_LICENSE_APACHE2
similarity index 100%
rename from media/libstagefright/mpeg2ts/MODULE_LICENSE_APACHE2
rename to media/module/mpeg2ts/MODULE_LICENSE_APACHE2
diff --git a/media/libstagefright/mpeg2ts/NOTICE b/media/module/mpeg2ts/NOTICE
similarity index 100%
rename from media/libstagefright/mpeg2ts/NOTICE
rename to media/module/mpeg2ts/NOTICE
diff --git a/media/libstagefright/mpeg2ts/TEST_MAPPING b/media/module/mpeg2ts/TEST_MAPPING
similarity index 100%
rename from media/libstagefright/mpeg2ts/TEST_MAPPING
rename to media/module/mpeg2ts/TEST_MAPPING
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h b/media/module/mpeg2ts/include/mpeg2ts/ATSParser.h
similarity index 96%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h
rename to media/module/mpeg2ts/include/mpeg2ts/ATSParser.h
index 49578d3..b658c5a 100644
--- a/media/libstagefright/mpeg2ts/include/mpeg2ts/ATSParser.h
+++ b/media/module/mpeg2ts/include/mpeg2ts/ATSParser.h
@@ -157,6 +157,9 @@
         STREAMTYPE_LPCM_AC3             = 0x83,
         STREAMTYPE_EAC3                 = 0x87,
 
+        // DTS audio stream type which contains only Core substream
+        STREAMTYPE_DTS                  = 0x8A,
+
         //Sample Encrypted types
         STREAMTYPE_H264_ENCRYPTED       = 0xDB,
         STREAMTYPE_AAC_ENCRYPTED        = 0xCF,
@@ -168,6 +171,7 @@
         DESCRIPTOR_CA                   = 0x09,
 
         // DVB BlueBook A038 Table 12
+        DESCRIPTOR_DTS                  = 0x7B,
         DESCRIPTOR_DVB_EXTENSION        = 0x7F,
     };
 
@@ -175,6 +179,8 @@
     enum {
         EXT_DESCRIPTOR_DVB_AC4                  = 0x15,
         EXT_DESCRIPTOR_DVB_AUDIO_PRESELECTION   = 0x19,
+        EXT_DESCRIPTOR_DVB_DTS_HD               = 0x0E,
+        EXT_DESCRIPTOR_DVB_DTS_UHD              = 0x21,
         EXT_DESCRIPTOR_DVB_RESERVED_MAX         = 0x7F,
     };
 
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h b/media/module/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
rename to media/module/mpeg2ts/include/mpeg2ts/AnotherPacketSource.h
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/CasManager.h b/media/module/mpeg2ts/include/mpeg2ts/CasManager.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/CasManager.h
rename to media/module/mpeg2ts/include/mpeg2ts/CasManager.h
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h b/media/module/mpeg2ts/include/mpeg2ts/ESQueue.h
similarity index 96%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h
rename to media/module/mpeg2ts/include/mpeg2ts/ESQueue.h
index a06bd6a..550a0e4 100644
--- a/media/libstagefright/mpeg2ts/include/mpeg2ts/ESQueue.h
+++ b/media/module/mpeg2ts/include/mpeg2ts/ESQueue.h
@@ -45,6 +45,9 @@
         MPEG4_VIDEO,
         PCM_AUDIO,
         METADATA,
+        DTS,
+        DTS_HD,
+        DTS_UHD,
     };
 
     enum Flags {
@@ -125,6 +128,8 @@
     sp<ABuffer> dequeueAccessUnitMPEG4Video();
     sp<ABuffer> dequeueAccessUnitPCMAudio();
     sp<ABuffer> dequeueAccessUnitMetadata();
+    sp<ABuffer> dequeueAccessUnitDTSOrDTSHD();
+    sp<ABuffer> dequeueAccessUnitDTSUHD();
 
     // consume a logical (compressed) access unit of size "size",
     // returns its timestamp in us (or -1 if no time information).
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h b/media/module/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
rename to media/module/mpeg2ts/include/mpeg2ts/HlsSampleDecryptor.h
diff --git a/media/libstagefright/mpeg2ts/include/mpeg2ts/SampleDecryptor.h b/media/module/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
rename to media/module/mpeg2ts/include/mpeg2ts/SampleDecryptor.h
diff --git a/media/libstagefright/mpeg2ts/test/Android.bp b/media/module/mpeg2ts/test/Android.bp
similarity index 92%
rename from media/libstagefright/mpeg2ts/test/Android.bp
rename to media/module/mpeg2ts/test/Android.bp
index 34a8d3e..4b1bacd 100644
--- a/media/libstagefright/mpeg2ts/test/Android.bp
+++ b/media/module/mpeg2ts/test/Android.bp
@@ -74,4 +74,7 @@
             "signed-integer-overflow",
         ],
     },
+    data: [
+        ":https://storage.googleapis.com/android_media/frameworks/av/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.zip?unzip=true",
+    ],
 }
diff --git a/media/libstagefright/mpeg2ts/test/AndroidTest.xml b/media/module/mpeg2ts/test/AndroidTest.xml
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/AndroidTest.xml
rename to media/module/mpeg2ts/test/AndroidTest.xml
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp b/media/module/mpeg2ts/test/Mpeg2tsUnitTest.cpp
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTest.cpp
rename to media/module/mpeg2ts/test/Mpeg2tsUnitTest.cpp
diff --git a/media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h b/media/module/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
rename to media/module/mpeg2ts/test/Mpeg2tsUnitTestEnvironment.h
diff --git a/media/libstagefright/mpeg2ts/test/README.md b/media/module/mpeg2ts/test/README.md
similarity index 100%
rename from media/libstagefright/mpeg2ts/test/README.md
rename to media/module/mpeg2ts/test/README.md
diff --git a/services/mediatranscoding/.clang-format b/media/module/service.mediatranscoding/.clang-format
similarity index 100%
rename from services/mediatranscoding/.clang-format
rename to media/module/service.mediatranscoding/.clang-format
diff --git a/services/mediatranscoding/Android.bp b/media/module/service.mediatranscoding/Android.bp
similarity index 96%
rename from services/mediatranscoding/Android.bp
rename to media/module/service.mediatranscoding/Android.bp
index fa5eb4e..37f354b 100644
--- a/services/mediatranscoding/Android.bp
+++ b/media/module/service.mediatranscoding/Android.bp
@@ -26,6 +26,10 @@
         "SimulatedTranscoder.cpp",
     ],
 
+    export_include_dirs: [
+        ".",
+    ],
+
     min_sdk_version: "29",
     apex_available: [
         "com.android.media",
diff --git a/services/mediatranscoding/MODULE_LICENSE_APACHE2 b/media/module/service.mediatranscoding/MODULE_LICENSE_APACHE2
similarity index 100%
rename from services/mediatranscoding/MODULE_LICENSE_APACHE2
rename to media/module/service.mediatranscoding/MODULE_LICENSE_APACHE2
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/media/module/service.mediatranscoding/MediaTranscodingService.cpp
similarity index 100%
rename from services/mediatranscoding/MediaTranscodingService.cpp
rename to media/module/service.mediatranscoding/MediaTranscodingService.cpp
diff --git a/services/mediatranscoding/MediaTranscodingService.h b/media/module/service.mediatranscoding/MediaTranscodingService.h
similarity index 100%
rename from services/mediatranscoding/MediaTranscodingService.h
rename to media/module/service.mediatranscoding/MediaTranscodingService.h
diff --git a/services/mediatranscoding/NOTICE b/media/module/service.mediatranscoding/NOTICE
similarity index 100%
rename from services/mediatranscoding/NOTICE
rename to media/module/service.mediatranscoding/NOTICE
diff --git a/services/mediatranscoding/OWNERS b/media/module/service.mediatranscoding/OWNERS
similarity index 100%
rename from services/mediatranscoding/OWNERS
rename to media/module/service.mediatranscoding/OWNERS
diff --git a/services/mediatranscoding/SimulatedTranscoder.cpp b/media/module/service.mediatranscoding/SimulatedTranscoder.cpp
similarity index 100%
rename from services/mediatranscoding/SimulatedTranscoder.cpp
rename to media/module/service.mediatranscoding/SimulatedTranscoder.cpp
diff --git a/services/mediatranscoding/SimulatedTranscoder.h b/media/module/service.mediatranscoding/SimulatedTranscoder.h
similarity index 100%
rename from services/mediatranscoding/SimulatedTranscoder.h
rename to media/module/service.mediatranscoding/SimulatedTranscoder.h
diff --git a/services/mediatranscoding/main_mediatranscodingservice.cpp b/media/module/service.mediatranscoding/main_mediatranscodingservice.cpp
similarity index 100%
rename from services/mediatranscoding/main_mediatranscodingservice.cpp
rename to media/module/service.mediatranscoding/main_mediatranscodingservice.cpp
diff --git a/services/mediatranscoding/tests/Android.bp b/media/module/service.mediatranscoding/tests/Android.bp
similarity index 95%
rename from services/mediatranscoding/tests/Android.bp
rename to media/module/service.mediatranscoding/tests/Android.bp
index ae13656..97fbd4c 100644
--- a/services/mediatranscoding/tests/Android.bp
+++ b/media/module/service.mediatranscoding/tests/Android.bp
@@ -20,10 +20,6 @@
         "-Wextra",
     ],
 
-    include_dirs: [
-        "frameworks/av/services/mediatranscoding",
-    ],
-
     shared_libs: [
         "libactivitymanager_aidl",
         "libbinder",
diff --git a/services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h b/media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
similarity index 100%
rename from services/mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
rename to media/module/service.mediatranscoding/tests/MediaTranscodingServiceTestHelper.h
diff --git a/services/mediatranscoding/tests/README.txt b/media/module/service.mediatranscoding/tests/README.txt
similarity index 100%
rename from services/mediatranscoding/tests/README.txt
rename to media/module/service.mediatranscoding/tests/README.txt
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/Android.bp
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppA.xml
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppB.xml
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/TestAppC.xml
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/MainActivity.java
diff --git a/services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java b/media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java
similarity index 100%
rename from services/mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java
rename to media/module/service.mediatranscoding/tests/TranscodingUidPolicyTestApp/src/com/android/tests/transcoding/ResourcePolicyTestActivity.java
diff --git a/services/mediatranscoding/tests/build_and_run_all_unit_tests.sh b/media/module/service.mediatranscoding/tests/build_and_run_all_unit_tests.sh
similarity index 100%
rename from services/mediatranscoding/tests/build_and_run_all_unit_tests.sh
rename to media/module/service.mediatranscoding/tests/build_and_run_all_unit_tests.sh
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp b/media/module/service.mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
similarity index 100%
rename from services/mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
rename to media/module/service.mediatranscoding/tests/mediatranscodingservice_real_tests.cpp
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp b/media/module/service.mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
similarity index 100%
rename from services/mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
rename to media/module/service.mediatranscoding/tests/mediatranscodingservice_resource_tests.cpp
diff --git a/services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp b/media/module/service.mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
similarity index 100%
rename from services/mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
rename to media/module/service.mediatranscoding/tests/mediatranscodingservice_simulated_tests.cpp
diff --git a/media/mtp/Android.bp b/media/mtp/Android.bp
index 97e2a22..719d05a 100644
--- a/media/mtp/Android.bp
+++ b/media/mtp/Android.bp
@@ -31,8 +31,8 @@
     ],
 }
 
-cc_library_shared {
-    name: "libmtp",
+cc_defaults {
+    name: "libmtp_defaults",
     srcs: [
         "MtpDataPacket.cpp",
         "MtpDebug.cpp",
@@ -71,3 +71,14 @@
     ],
     header_libs: ["libcutils_headers"],
 }
+
+cc_library_shared {
+    name: "libmtp",
+    defaults: ["libmtp_defaults"],
+}
+
+cc_library_shared {
+    name: "libmtp_fuzz",
+    defaults: ["libmtp_defaults"],
+    cflags: ["-DMTP_FUZZER"],
+}
diff --git a/media/mtp/MtpDescriptors.h b/media/mtp/MtpDescriptors.h
index d600a24..9b98a71 100644
--- a/media/mtp/MtpDescriptors.h
+++ b/media/mtp/MtpDescriptors.h
@@ -23,6 +23,17 @@
 
 namespace android {
 
+#ifdef MTP_FUZZER
+constexpr char FFS_MTP_EP0[] = "/data/local/tmp/usb-ffs/mtp/ep0";
+constexpr char FFS_MTP_EP_IN[] = "/data/local/tmp/usb-ffs/mtp/ep1";
+constexpr char FFS_MTP_EP_OUT[] = "/data/local/tmp/usb-ffs/mtp/ep2";
+constexpr char FFS_MTP_EP_INTR[] = "/data/local/tmp/usb-ffs/mtp/ep3";
+
+constexpr char FFS_PTP_EP0[] = "/data/local/tmp/usb-ffs/ptp/ep0";
+constexpr char FFS_PTP_EP_IN[] = "/data/local/tmp/usb-ffs/ptp/ep1";
+constexpr char FFS_PTP_EP_OUT[] = "/data/local/tmp/usb-ffs/ptp/ep2";
+constexpr char FFS_PTP_EP_INTR[] = "/data/local/tmp/usb-ffs/ptp/ep3";
+#else
 constexpr char FFS_MTP_EP0[] = "/dev/usb-ffs/mtp/ep0";
 constexpr char FFS_MTP_EP_IN[] = "/dev/usb-ffs/mtp/ep1";
 constexpr char FFS_MTP_EP_OUT[] = "/dev/usb-ffs/mtp/ep2";
@@ -32,6 +43,7 @@
 constexpr char FFS_PTP_EP_IN[] = "/dev/usb-ffs/ptp/ep1";
 constexpr char FFS_PTP_EP_OUT[] = "/dev/usb-ffs/ptp/ep2";
 constexpr char FFS_PTP_EP_INTR[] = "/dev/usb-ffs/ptp/ep3";
+#endif
 
 constexpr int MAX_PACKET_SIZE_FS = 64;
 constexpr int MAX_PACKET_SIZE_HS = 512;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 6fcf119..d917772 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -985,7 +985,7 @@
 
     int type = storage->getType();
     if (type == MTP_STORAGE_REMOVABLE_RAM) {
-        std::string str = android::base::Trim((const char*)name);
+        std::string str = android::base::Trim(name);
         name.set(str.c_str());
     }
     ALOGV("name: %s format: 0x%04X (%s)\n", (const char*)name, format,
diff --git a/media/mtp/MtpStringBuffer.h b/media/mtp/MtpStringBuffer.h
index 4cec58a..30d1bc1 100644
--- a/media/mtp/MtpStringBuffer.h
+++ b/media/mtp/MtpStringBuffer.h
@@ -20,6 +20,7 @@
 #include <log/log.h>
 #include <stdint.h>
 #include <string>
+#include <string_view>
 
 // Max Character number of a MTP String
 #define MTP_STRING_MAX_CHARACTER_NUMBER             255
@@ -55,6 +56,7 @@
     inline int      size() const { return mString.length(); }
 
     inline operator const char*() const { return mString.c_str(); }
+    operator std::string_view() const { return mString; }
 };
 
 inline void MtpStringBuffer::append(const char* other) {
diff --git a/media/mtp/tests/MtpFuzzer/Android.bp b/media/mtp/tests/MtpFuzzer/Android.bp
index 5365f4b..9e41680 100644
--- a/media/mtp/tests/MtpFuzzer/Android.bp
+++ b/media/mtp/tests/MtpFuzzer/Android.bp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package {
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
@@ -6,29 +22,20 @@
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_av_media_mtp_license"],
 }
-
-cc_fuzz {
-    name: "mtp_fuzzer",
-    srcs: [
-        "mtp_fuzzer.cpp",
-        "MtpMockDatabase.cpp",
-    ],
+cc_defaults {
+    name: "mtp_fuzzer_defaults",
     shared_libs: [
-	"libmtp",
-	"libbase",
-	"liblog",
-	"libutils",
+        "libbase",
+        "liblog",
+        "libutils",
     ],
+    static_libs: ["libc++fs",],
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
-        "-DMTP_DEVICE",
         "-Wno-unused-parameter",
     ],
-    dictionary: "mtp_fuzzer.dict",
-    corpus: ["corpus/*"],
-
     fuzz_config: {
 
         cc: ["jameswei@google.com"],
@@ -38,3 +45,107 @@
         ],
     },
 }
+cc_fuzz {
+    name: "mtp_fuzzer",
+    srcs: [
+        "mtp_fuzzer.cpp",
+        "MtpMockDatabase.cpp",
+    ],
+    cflags: ["-DMTP_DEVICE",],
+    shared_libs: ["libmtp",],
+    defaults: ["mtp_fuzzer_defaults"],
+    dictionary: "mtp_fuzzer.dict",
+    corpus: ["corpus/*"],
+}
+
+cc_defaults {
+    name: "mtp_property_fuzzer_defaults",
+    srcs: ["mtp_property_fuzzer.cpp"],
+    shared_libs: [
+        "libmtp",
+        "libasyncio",
+        "libusbhost",
+    ],
+    defaults: ["mtp_fuzzer_defaults"],
+}
+
+cc_fuzz {
+     name: "mtp_device_property_fuzzer",
+     defaults: ["mtp_property_fuzzer_defaults"],
+     cflags: [
+         "-DMTP_DEVICE",
+     ],
+}
+
+cc_fuzz {
+     name: "mtp_host_property_fuzzer",
+     defaults: ["mtp_property_fuzzer_defaults"],
+     cflags: [
+         "-DMTP_HOST",
+     ],
+}
+
+cc_fuzz {
+    name: "mtp_handle_fuzzer",
+    srcs: ["mtp_handle_fuzzer.cpp"],
+    shared_libs: ["libmtp_fuzz"],
+    defaults: ["mtp_fuzzer_defaults"],
+    cflags: ["-DMTP_FUZZER"],
+}
+
+cc_defaults  {
+     name: "mtp_packet_defaults",
+     shared_libs: [
+        "libmtp",
+        "libasyncio",
+        "libusbhost",
+     ],
+     defaults: ["mtp_fuzzer_defaults"],
+     cflags: [
+         "-DMTP_HOST",
+         "-DMTP_DEVICE",
+     ],
+}
+
+cc_fuzz {
+     name: "mtp_packet_fuzzer",
+     srcs: ["mtp_packet_fuzzer.cpp"],
+     defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+     name: "mtp_device_fuzzer",
+     srcs: ["mtp_device_fuzzer.cpp"],
+     shared_libs: [
+        "libmtp",
+        "libusbhost",
+     ],
+     defaults: ["mtp_fuzzer_defaults"],
+     cflags: [
+         "-DMTP_DEVICE",
+     ],
+}
+
+cc_fuzz {
+     name: "mtp_request_packet_fuzzer",
+     srcs: ["mtp_request_packet_fuzzer.cpp"],
+     defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+     name: "mtp_event_packet_fuzzer",
+     srcs: ["mtp_event_packet_fuzzer.cpp"],
+     defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+     name: "mtp_response_packet_fuzzer",
+     srcs: ["mtp_response_packet_fuzzer.cpp"],
+     defaults: ["mtp_packet_defaults"],
+}
+
+cc_fuzz {
+     name: "mtp_data_packet_fuzzer",
+     srcs: ["mtp_data_packet_fuzzer.cpp"],
+     defaults: ["mtp_packet_defaults"],
+}
diff --git a/media/mtp/tests/MtpFuzzer/MtpPacketFuzzerUtils.h b/media/mtp/tests/MtpFuzzer/MtpPacketFuzzerUtils.h
new file mode 100644
index 0000000..87fea9f
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/MtpPacketFuzzerUtils.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpStringBuffer.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <linux/usbdevice_fs.h>
+#include <sys/mman.h>
+#include <usbhost/usbhost.h>
+#include <MtpTypes.h>
+
+using namespace android;
+constexpr UrbPacketDivisionMode kUrbPacketDivisionModes[] = {FIRST_PACKET_ONLY_HEADER,
+                                                             FIRST_PACKET_HAS_PAYLOAD};
+
+constexpr size_t kMinSize = 0;
+constexpr size_t kMaxSize = 1000;
+constexpr size_t kMaxLength = 1000;
+
+class MtpPacketFuzzerUtils {
+  protected:
+    struct usb_request mUsbRequest;
+    struct usbdevfs_urb* mUsbDevFsUrb;
+    std::string mPath;
+
+    void fillFd(int32_t& fd, FuzzedDataProvider* fdp) {
+        if (fdp->ConsumeBool()) {
+            std::string text = fdp->ConsumeRandomLengthString(kMaxLength);
+            write(fd, text.c_str(), text.length());
+        }
+    };
+
+    void fillFilePath(FuzzedDataProvider* fdp) {
+       mPath= fdp->ConsumeRandomLengthString(kMaxLength);
+    };
+
+    void fillUsbDevFsUrb(FuzzedDataProvider* fdp) {
+        mUsbDevFsUrb->type = fdp->ConsumeIntegral<unsigned char>();
+        mUsbDevFsUrb->endpoint = fdp->ConsumeIntegral<unsigned char>();
+        mUsbDevFsUrb->flags = fdp->ConsumeIntegral<uint32_t>();
+        std::vector<uint8_t> buffer =
+                fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+        mUsbDevFsUrb->buffer = static_cast<void*>(buffer.data());
+        mUsbDevFsUrb->buffer_length = buffer.size();
+        mUsbDevFsUrb->actual_length = fdp->ConsumeIntegral<uint32_t>();
+        mUsbDevFsUrb->start_frame = fdp->ConsumeIntegral<uint32_t>();
+        mUsbDevFsUrb->number_of_packets = fdp->ConsumeIntegral<uint32_t>();
+        mUsbDevFsUrb->stream_id = fdp->ConsumeIntegral<uint32_t>();
+        mUsbDevFsUrb->error_count = fdp->ConsumeIntegral<size_t>();
+        mUsbDevFsUrb->signr = fdp->ConsumeIntegral<uint32_t>();
+        std::vector<uint8_t> userBuffer = (fdp->ConsumeBytes<uint8_t>(
+                fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)));
+        mUsbDevFsUrb->usercontext = static_cast<void*>(userBuffer.data());
+        mUsbDevFsUrb->iso_frame_desc[0].length = fdp->ConsumeIntegral<uint32_t>();
+        mUsbDevFsUrb->iso_frame_desc[0].actual_length = fdp->ConsumeIntegral<uint32_t>();
+    };
+
+    void fillUsbRequest(int32_t& fd, FuzzedDataProvider* fdp) {
+        fillUsbDevFsUrb(fdp);
+        fillFd(fd, fdp);
+        std::vector<uint8_t> buffer =
+                fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+        mUsbRequest.buffer = static_cast<void*>(buffer.data());
+        mUsbRequest.buffer_length = buffer.size();
+        mUsbRequest.actual_length = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+        mUsbRequest.max_packet_size = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+        mUsbRequest.private_data = static_cast<void*>(mUsbDevFsUrb);
+        mUsbRequest.endpoint = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+        std::vector<uint8_t> clientBuffer = (fdp->ConsumeBytes<uint8_t>(
+                fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)));
+        mUsbRequest.client_data = static_cast<void*>(clientBuffer.data());
+    };
+
+    template <typename Object>
+    void writeHandle(Object obj, FuzzedDataProvider* fdp) {
+        MtpDevHandle handle;
+        std::vector<uint8_t> initData =
+                fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+        handle.write(initData.data(), initData.size());
+        obj->write(&handle);
+    };
+};
diff --git a/media/mtp/tests/MtpFuzzer/README.md b/media/mtp/tests/MtpFuzzer/README.md
new file mode 100644
index 0000000..7efaf67
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/README.md
@@ -0,0 +1,210 @@
+# Fuzzers for libmtp
+
+## Table of contents
++ [mtp_fuzzer](#MtpServer)
++ [mtp_host_property_fuzzer](#MtpHostProperty)
++ [mtp_device_property_fuzzer](#MtpDeviceProperty)
++ [mtp_handle_fuzzer](#MtpHandle)
++ [mtp_packet_fuzzer](#MtpPacket)
+ + [mtp_device_fuzzer](#MtpDevice)
++ [mtp_request_packet_fuzzer](#MtpRequestPacket)
++ [mtp_event_packet_fuzzer](#MtpEventPacket)
++ [mtp_response_packet_fuzzer](#MtpResponsePacket)
++ [mtp_data_packet_fuzzer](#MtpDataPacket)
+
+# <a name="MtpServer"></a> Fuzzer for MtpServer
+
+MtpServer supports the following parameters:
+1. PacketData (parameter name: "packetData")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`packetData`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_fuzzer/mtp_fuzzer corpus/ -dict=mtp_fuzzer.dict
+```
+
+# <a name="MtpHostProperty"></a> Fuzzer for MtpHostProperty
+
+MtpHostProperty supports the following parameters:
+1. Feasible Type (parameter name: "kFeasibleTypes")
+2. UrbPacket Division Mode (parameter name: "kUrbPacketDivisionModes")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+| `kFeasibleType`| 1. `MTP_TYPE_UNDEFINED`, 2. `MTP_TYPE_INT8`, 3.`MTP_TYPE_UINT8`, 4.`MTP_TYPE_INT16`, 5.`MTP_TYPE_UINT16`, 6.`MTP_TYPE_INT32`, 7.`MTP_TYPE_UINT32`, 8.`MTP_TYPE_INT64`, 9.`MTP_TYPE_UINT64`, 10.`MTP_TYPE_INT128`, 11.`MTP_TYPE_UINT128`, 12.`MTP_TYPE_AINT8`, 13.`MTP_TYPE_AUINT8`, 14.`MTP_TYPE_AINT16`, 15.`MTP_TYPE_AUINT16`, 16.`MTP_TYPE_AINT32`, 17.`MTP_TYPE_AUINT32`, 18.`MTP_TYPE_AINT64`, 19.`MTP_TYPE_AUINT64`, 20.`MTP_TYPE_AINT128`, 21.`MTP_TYPE_AUINT128`, 22.`MTP_TYPE_STR`,| Value obtained from FuzzedDataProvider|
+|`kUrbPacketDivisionMode`| 1. `FIRST_PACKET_ONLY_HEADER`, 2. `FIRST_PACKET_HAS_PAYLOAD`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_host_property_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_host_property_fuzzer/mtp_host_property_fuzzer
+```
+
+# <a name="MtpDeviceProperty"></a> Fuzzer for MtpDeviceProperty
+
+MtpDeviceProperty supports the following parameters:
+1. Feasible Type (parameter name: "kFeasibleType")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+| `kFeasibleType`| 1. `MTP_TYPE_UNDEFINED`, 2. `MTP_TYPE_INT8`, 3.`MTP_TYPE_UINT8`, 4.`MTP_TYPE_INT16`, 5.`MTP_TYPE_UINT16`, 6.`MTP_TYPE_INT32`, 7.`MTP_TYPE_UINT32`, 8.`MTP_TYPE_INT64`, 9.`MTP_TYPE_UINT64`, 10.`MTP_TYPE_INT128`, 11.`MTP_TYPE_UINT128`, 12.`MTP_TYPE_AINT8`, 13.`MTP_TYPE_AUINT8`, 14.`MTP_TYPE_AINT16`, 15.`MTP_TYPE_AUINT16`, 16.`MTP_TYPE_AINT32`, 17.`MTP_TYPE_AUINT32`, 18.`MTP_TYPE_AINT64`, 19.`MTP_TYPE_AUINT64`, 20.`MTP_TYPE_AINT128`, 21.`MTP_TYPE_AUINT128`, 22.`MTP_TYPE_STR`,| Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_device_property_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_device_property_fuzzer/mtp_device_property_fuzzer
+```
+
+# <a name="MtpHandle"></a>Fuzzer for MtpHandle
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_handle_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_handle_fuzzer/mtp_handle_fuzzer
+```
+
+# <a name="MtpPacket"></a> Fuzzer for MtpPacket
+
+MtpPacket supports the following parameters:
+1. bufferSize (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`bufferSize`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_packet_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_packet_fuzzer/mtp_packet_fuzzer
+```
+
+# <a name="MtpDevice"></a> Fuzzer for MtpDevice
+
+MtpDevice supports the following parameters:
+1. Device Name (parameter name: "deviceName")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`deviceName`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_device_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_device_fuzzer/mtp_device_fuzzer
+```
+
+# <a name="MtpRequestPacket"></a> Fuzzer for MtpRequestPacket
+
+MtpRequestPacket supports the following parameters:
+1. Data (parameter name: "data")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`data`| Vector of positive Integer |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_request_packet_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_request_packet_fuzzer/mtp_request_packet_fuzzer
+```
+
+# <a name="MtpEventPacket"></a> Fuzzer for MtpEventPacket
+
+MtpEventPacket supports the following parameters:
+1. Size (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`size`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_event_packet_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_event_packet_fuzzer/mtp_event_packet_fuzzer
+```
+
+# <a name="MtpResponsePacket"></a> Fuzzer for MtpResponsePacket
+
+MtpResponsePacket supports the following parameters:
+1. Size (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`size`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_response_packet_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_response_packet_fuzzer/mtp_response_packet_fuzzer
+```
+
+# <a name="MtpDataPacket"></a> Fuzzer for MtpDataPacket
+
+MtpDataPacket supports the following parameters:
+1. UrbPacket Division Mode (parameter name: "kUrbPacketDivisionModes")
+2. Size (parameter name: "size")
+
+| Parameter| Valid Values |Configured Value|
+|-------------|----------|----- |
+|`kUrbPacketDivisionMode`| 1. `FIRST_PACKET_ONLY_HEADER`, 2. `FIRST_PACKET_HAS_PAYLOAD`, |Value obtained from FuzzedDataProvider|
+|`size`| Integer `1` to `1000`, |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) mtp_data_packet_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/mtp_data_packet_fuzzer/mtp_data_packet_fuzzer
+```
diff --git a/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt b/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt
new file mode 100644
index 0000000..71f2836
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/corpus/6-mtp-open_session_send_object_info.pkt
Binary files differ
diff --git a/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
new file mode 100644
index 0000000..f5faf77
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_data_packet_fuzzer.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDataPacket.h>
+#include <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String16.h>
+
+using namespace android;
+
+class MtpDataPacketFuzzer : MtpPacketFuzzerUtils {
+  public:
+    MtpDataPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                   sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpDataPacketFuzzer() { free(mUsbDevFsUrb); };
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void MtpDataPacketFuzzer::process() {
+    MtpDataPacket mtpDataPacket;
+    while (mFdp.remaining_bytes() > 0) {
+        auto mtpDataAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() { mtpDataPacket.allocate(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); },
+                [&]() { mtpDataPacket.reset(); },
+                [&]() {
+                    mtpDataPacket.setOperationCode(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    mtpDataPacket.setTransactionID(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    Int8List* result = mtpDataPacket.getAInt8();
+                    delete result;
+                },
+                [&]() {
+                    Int16List* result = mtpDataPacket.getAInt16();
+                    delete result;
+                },
+                [&]() {
+                    Int32List* result = mtpDataPacket.getAInt32();
+                    delete result;
+                },
+                [&]() {
+                    Int64List* result = mtpDataPacket.getAInt64();
+                    delete result;
+                },
+                [&]() {
+                    UInt8List* result = mtpDataPacket.getAUInt8();
+                    delete result;
+                },
+                [&]() {
+                    UInt16List* result = mtpDataPacket.getAUInt16();
+                    delete result;
+                },
+                [&]() {
+                    UInt32List* result = mtpDataPacket.getAUInt32();
+                    delete result;
+                },
+                [&]() {
+                    UInt64List* result = mtpDataPacket.getAUInt64();
+                    delete result;
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<uint8_t> initData =
+                                mFdp.ConsumeBytes<uint8_t>(mFdp.ConsumeIntegral<uint8_t>());
+                        mtpDataPacket.putAUInt8(initData.data(), initData.size());
+                    } else {
+                        mtpDataPacket.putAUInt8(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        uint16_t arr[size];
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr[idx] = mFdp.ConsumeIntegral<uint16_t>();
+                        }
+                        mtpDataPacket.putAUInt16(arr, size);
+                    } else {
+                        mtpDataPacket.putAUInt16(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        uint32_t arr[size];
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr[idx] = mFdp.ConsumeIntegral<uint32_t>();
+                        }
+                        mtpDataPacket.putAUInt32(arr, size);
+                    } else {
+                        mtpDataPacket.putAUInt32(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        uint64_t arr[size];
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr[idx] = mFdp.ConsumeIntegral<uint64_t>();
+                        }
+                        mtpDataPacket.putAUInt64(arr, size);
+                    } else {
+                        mtpDataPacket.putAUInt64(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        int64_t arr[size];
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr[idx] = mFdp.ConsumeIntegral<int64_t>();
+                        }
+                        mtpDataPacket.putAInt64(arr, size);
+                    } else {
+                        mtpDataPacket.putAInt64(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<uint16_t> arr;
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr.push_back(mFdp.ConsumeIntegral<uint16_t>());
+                        }
+                        mtpDataPacket.putAUInt16(&arr);
+                    } else {
+                        mtpDataPacket.putAUInt16(nullptr);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<uint32_t> arr;
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr.push_back(mFdp.ConsumeIntegral<uint32_t>());
+                        }
+                        mtpDataPacket.putAUInt32(&arr);
+                    } else {
+                        mtpDataPacket.putAUInt32(nullptr);
+                    }
+                },
+
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        size_t size = mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
+                        int32_t arr[size];
+                        for (size_t idx = 0; idx < size; ++idx) {
+                            arr[idx] = mFdp.ConsumeIntegral<int32_t>();
+                        }
+                        mtpDataPacket.putAInt32(arr, size);
+                    } else {
+                        mtpDataPacket.putAInt32(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        mtpDataPacket.putString(
+                                (mFdp.ConsumeRandomLengthString(kMaxLength)).c_str());
+                    } else {
+                        mtpDataPacket.putString(static_cast<char*>(nullptr));
+                    }
+                },
+                [&]() {
+                    android::MtpStringBuffer sBuffer(
+                            (mFdp.ConsumeRandomLengthString(kMaxLength)).c_str());
+                    if (mFdp.ConsumeBool()) {
+                        mtpDataPacket.getString(sBuffer);
+                    } else {
+                        mtpDataPacket.putString(sBuffer);
+                    }
+                },
+                [&]() {
+                    MtpDevHandle handle;
+                    handle.start(mFdp.ConsumeBool());
+                    std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
+                    char* data = const_cast<char*>(text.c_str());
+                    handle.read(static_cast<void*>(data), text.length());
+                    if (mFdp.ConsumeBool()) {
+                        mtpDataPacket.read(&handle);
+                    } else if (mFdp.ConsumeBool()) {
+                        mtpDataPacket.write(&handle);
+                    } else {
+                        std::string textData = mFdp.ConsumeRandomLengthString(kMaxLength);
+                        char* Data = const_cast<char*>(textData.c_str());
+                        mtpDataPacket.writeData(&handle, static_cast<void*>(Data),
+                                                textData.length());
+                    }
+                    handle.close();
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
+                        android::String16 s(str.c_str());
+                        char16_t* data = const_cast<char16_t*>(s.string());
+                        mtpDataPacket.putString(reinterpret_cast<uint16_t*>(data));
+                    } else {
+                        mtpDataPacket.putString(static_cast<uint16_t*>(nullptr));
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<int8_t> data = mFdp.ConsumeBytes<int8_t>(
+                                mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+                        mtpDataPacket.putAInt8(data.data(), data.size());
+                    } else {
+                        mtpDataPacket.putAInt8(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<uint8_t> data = mFdp.ConsumeBytes<uint8_t>(
+                                mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+                        mtpDataPacket.putAUInt8(data.data(), data.size());
+                    } else {
+                        mtpDataPacket.putAUInt8(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    std::vector<int8_t> data = mFdp.ConsumeBytes<int8_t>(
+                            mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+                    mtpDataPacket.readData(&mUsbRequest, data.data(), data.size());
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpDataPacket.write(
+                            &mUsbRequest,
+                            mFdp.PickValueInArray<UrbPacketDivisionMode>(kUrbPacketDivisionModes),
+                            fd, mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpDataPacket.read(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpDataPacket.write(&mUsbRequest, mFdp.PickValueInArray<UrbPacketDivisionMode>(
+                                                             kUrbPacketDivisionModes));
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpDataPacket.readDataHeader(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpDataPacket.readDataAsync(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpDataPacket.readDataWait(mUsbRequest.dev);
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    if (mFdp.ConsumeBool()) {
+                        std::vector<int16_t> data;
+                        for (size_t idx = 0;
+                             idx < mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize); ++idx) {
+                            data.push_back(mFdp.ConsumeIntegral<int16_t>());
+                        }
+                        mtpDataPacket.putAInt16(data.data(), data.size());
+                    } else {
+                        mtpDataPacket.putAInt16(nullptr, 0);
+                    }
+                },
+                [&]() {
+                    int32_t arr[4];
+                    for (size_t idx = 0; idx < 4; ++idx) {
+                        arr[idx] = mFdp.ConsumeIntegral<int32_t>();
+                    }
+                    mtpDataPacket.putInt128(arr);
+                },
+                [&]() { mtpDataPacket.putInt64(mFdp.ConsumeIntegral<int64_t>()); },
+                [&]() {
+                    int16_t out;
+                    mtpDataPacket.getInt16(out);
+                },
+                [&]() {
+                    int32_t out;
+                    mtpDataPacket.getInt32(out);
+                },
+                [&]() {
+                    int8_t out;
+                    mtpDataPacket.getInt8(out);
+                },
+                [&]() {
+                    uint32_t arr[4];
+                    for (size_t idx = 0; idx < 4; ++idx) {
+                        arr[idx] = mFdp.ConsumeIntegral<uint32_t>();
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        mtpDataPacket.putUInt128(arr);
+                    } else {
+                        mtpDataPacket.getUInt128(arr);
+                    }
+                },
+                [&]() { mtpDataPacket.putUInt64(mFdp.ConsumeIntegral<uint64_t>()); },
+                [&]() {
+                    uint64_t out;
+                    mtpDataPacket.getUInt64(out);
+                },
+                [&]() { mtpDataPacket.putInt128(mFdp.ConsumeIntegral<int64_t>()); },
+                [&]() { mtpDataPacket.putUInt128(mFdp.ConsumeIntegral<uint64_t>()); },
+                [&]() {
+                    int32_t length;
+                    void* data = mtpDataPacket.getData(&length);
+                    free(data);
+                },
+        });
+        mtpDataAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpDataPacketFuzzer mtpDataPacketFuzzer(data, size);
+    mtpDataPacketFuzzer.process();
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
new file mode 100644
index 0000000..c32d28a
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_device_fuzzer.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDevHandle.h>
+#include <MtpDevice.h>
+#include <MtpDeviceInfo.h>
+#include <MtpObjectInfo.h>
+#include <MtpProperty.h>
+#include <MtpStorageInfo.h>
+#include <MtpStringBuffer.h>
+#include <android-base/unique_fd.h>
+#include <fcntl.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <linux/usb/ch9.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <usbhost/usbhost.h>
+
+using namespace android;
+
+constexpr int32_t kMaxStringLength = 20;
+constexpr int32_t kMaxBytes = 200;
+constexpr int32_t kMaxDataSize = 20;
+constexpr uint16_t kWMaxPacketSize = 64;
+constexpr uint16_t kEndpointsCount = 3;
+const std::string kInputFile = "/dev/null";
+const std::string kConfigFilePath = "/data/local/tmp/config";
+
+static bool readCallback(void* data, uint32_t offset, uint32_t length, void* clientData) {
+    return true;
+}
+
+struct fdDescriptors {
+    struct usb_interface_descriptor interface;
+    struct usb_endpoint_descriptor ep[kEndpointsCount];
+};
+
+fdDescriptors writeDescriptorsToFd(int32_t fd, FuzzedDataProvider& fdp) {
+    fdDescriptors desc;
+    desc.interface.bLength = sizeof(desc.interface);
+    desc.interface.bDescriptorType = USB_DT_INTERFACE;
+    desc.interface.bInterfaceNumber = fdp.ConsumeIntegral<uint8_t>();
+    desc.interface.bNumEndpoints = kEndpointsCount;
+    desc.interface.bInterfaceClass =
+            fdp.ConsumeBool() ? USB_CLASS_STILL_IMAGE : USB_CLASS_VENDOR_SPEC;
+    desc.interface.bInterfaceSubClass = fdp.ConsumeBool() ? 1 : 0xFF;
+    desc.interface.bInterfaceProtocol = fdp.ConsumeBool() ? 1 : 0;
+    desc.interface.iInterface = fdp.ConsumeIntegral<uint8_t>();
+    for (uint16_t idx = 0; idx < kEndpointsCount; ++idx) {
+        desc.ep[idx].bLength = sizeof(desc.ep[idx]);
+        desc.ep[idx].bDescriptorType = USB_DT_ENDPOINT;
+        desc.ep[idx].bEndpointAddress = idx | (fdp.ConsumeBool() ? USB_DIR_OUT : USB_DIR_IN);
+        desc.ep[idx].bmAttributes =
+                fdp.ConsumeBool() ? USB_ENDPOINT_XFER_BULK : USB_ENDPOINT_XFER_INT;
+        desc.ep[idx].wMaxPacketSize = kWMaxPacketSize;
+    }
+    write(fd, &desc, sizeof(fdDescriptors));
+    return desc;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    FuzzedDataProvider fdp(data, size);
+    int32_t fd = memfd_create(kConfigFilePath.c_str(), MFD_ALLOW_SEALING);
+    fdDescriptors descriptor = writeDescriptorsToFd(fd, fdp);
+    std::string deviceName = fdp.ConsumeRandomLengthString(kMaxStringLength);
+    usb_device* device = usb_device_new(deviceName.c_str(), fd);
+    MtpDevice mtpDevice(device, fdp.ConsumeIntegral<int32_t>(), &descriptor.ep[0],
+                        &descriptor.ep[1], &descriptor.ep[2]);
+    while (fdp.remaining_bytes()) {
+        auto mtpDeviceFunction = fdp.PickValueInArray<const std::function<void()>>(
+                {[&]() { mtpDevice.getStorageIDs(); },
+                 [&]() {
+                     mtpDevice.getStorageInfo(fdp.ConsumeIntegral<int32_t>() /* storageID */);
+                 },
+                 [&]() {
+                     mtpDevice.getObjectHandles(fdp.ConsumeIntegral<uint32_t>() /* storageID */,
+                                                fdp.ConsumeIntegral<uint16_t>() /* format */,
+                                                fdp.ConsumeIntegral<uint32_t>() /* parent */);
+                 },
+                 [&]() { mtpDevice.initialize(); },
+                 [&]() {
+                     int32_t outLength = 0;
+                     mtpDevice.getThumbnail(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+                                            outLength);
+                 },
+                 [&]() {
+                     MtpObjectInfo mtpObjectInfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
+                     std::string name = fdp.ConsumeRandomLengthString(kMaxStringLength);
+                     std::string keywords = fdp.ConsumeRandomLengthString(kMaxStringLength);
+                     mtpObjectInfo.mName = strdup(name.c_str());
+                     mtpObjectInfo.mKeywords = strdup(keywords.c_str());
+                     mtpDevice.sendObjectInfo(&mtpObjectInfo);
+                 },
+                 [&]() {
+                     mtpDevice.sendObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+                                          fdp.ConsumeIntegral<uint32_t>() /* size */, fd);
+                 },
+                 [&]() { mtpDevice.deleteObject(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+                 [&]() {
+                     mtpDevice.getObjectPropsSupported(
+                             fdp.ConsumeIntegral<uint16_t>() /* format */);
+                 },
+                 [&]() {
+                     MtpDataType dataType = fdp.ConsumeIntegral<int16_t>();
+                     MtpProperty mtpProperty(fdp.ConsumeIntegral<int16_t>() /* propCode */,
+                                             dataType, fdp.ConsumeBool() /* writeable */,
+                                             fdp.ConsumeIntegral<int32_t>() /* defaultValue */);
+                     if (dataType == MTP_TYPE_STR) {
+                         mtpProperty.setCurrentValue(
+                                 fdp.ConsumeRandomLengthString(kMaxStringLength).c_str());
+                     }
+                     mtpDevice.setDevicePropValueStr(&mtpProperty);
+                 },
+                 [&]() {
+                     mtpDevice.getObjectPropDesc(fdp.ConsumeIntegral<uint16_t>() /* code */,
+                                                 fdp.ConsumeIntegral<uint16_t>() /* format */);
+                 },
+                 [&]() {
+                     MtpProperty property;
+                     mtpDevice.getObjectPropValue(fdp.ConsumeIntegral<uint16_t>() /* handle */,
+                                                  &property);
+                 },
+                 [&]() {
+                     std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
+                     mtpDevice.readObject(
+                             fdp.ConsumeIntegral<uint32_t>() /* handle */, readCallback,
+                             fdp.ConsumeIntegral<uint32_t>() /* objectSize */, &clientData);
+                 },
+                 [&]() {
+                     std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
+                     uint32_t writtenSize = 0;
+                     mtpDevice.readPartialObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+                                                 fdp.ConsumeIntegral<uint32_t>() /* offset */,
+                                                 fdp.ConsumeIntegral<uint32_t>() /* size */,
+                                                 &writtenSize, readCallback, &clientData);
+                 },
+                 [&]() {
+                     std::vector<uint8_t> clientData = fdp.ConsumeBytes<uint8_t>(kMaxDataSize);
+                     uint32_t writtenSize = 0;
+                     mtpDevice.readPartialObject(fdp.ConsumeIntegral<uint32_t>() /* handle */,
+                                                 fdp.ConsumeIntegral<uint64_t>() /* offset */,
+                                                 fdp.ConsumeIntegral<uint32_t>() /* size */,
+                                                 &writtenSize, readCallback, &clientData);
+                 },
+                 [&]() {
+                     if (mtpDevice.submitEventRequest() != -1) {
+                         uint32_t parameters[3];
+                         mtpDevice.reapEventRequest(fdp.ConsumeIntegral<int32_t>() /* handle */,
+                                                    &parameters);
+                     }
+                 },
+                 [&]() {
+                     mtpDevice.discardEventRequest(fdp.ConsumeIntegral<int32_t>() /*handle*/);
+                 },
+                 [&]() {
+                     mtpDevice.discardEventRequest(fdp.ConsumeIntegral<int32_t>() /* handle */);
+                 },
+                 [&]() { mtpDevice.print(); },
+                 [&]() { mtpDevice.getDeviceName(); },
+                 [&]() { mtpDevice.getObjectInfo(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+                 [&]() { mtpDevice.getParent(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+                 [&]() { mtpDevice.getStorageID(fdp.ConsumeIntegral<uint32_t>() /* handle */); },
+                 [&]() { mtpDevice.getDevicePropDesc(fdp.ConsumeIntegral<uint16_t>() /* code */); },
+                 [&]() {
+                     mtpDevice.readObject(
+                             fdp.ConsumeIntegral<uint32_t>() /* handle */,
+                             fdp.ConsumeRandomLengthString(kMaxStringLength).c_str() /* destPath */,
+                             fdp.ConsumeIntegral<int32_t>() /* group */,
+                             fdp.ConsumeIntegral<int32_t>() /* perm */);
+                 },
+                 [&]() {
+                     int32_t filefd = open(kConfigFilePath.c_str(), O_CREAT | O_RDWR);
+                     mtpDevice.readObject(fdp.ConsumeIntegral<uint16_t>() /* handle */, filefd);
+                     close(filefd);
+                 },
+                 [&]() { MtpDevice::open(deviceName.c_str(), fd); },
+                 [&]() {
+                     MtpObjectInfo objectinfo(fdp.ConsumeIntegral<uint32_t>() /* handle */);
+                     MtpDataPacket mtpDataPacket;
+                     MtpDevHandle devHandle;
+                     std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
+                     mtpDataPacket.writeData(&devHandle, packet.data(), packet.size());
+                     objectinfo.read(mtpDataPacket);
+                     objectinfo.print();
+                 },
+                 [&]() {
+                     MtpStorageInfo storageInfo(fdp.ConsumeIntegral<uint32_t>() /* id */);
+                     MtpDataPacket mtpDataPacket;
+                     MtpDevHandle devHandle;
+                     std::vector<uint8_t> packet = fdp.ConsumeBytes<uint8_t>(kMaxBytes);
+                     mtpDataPacket.writeData(&devHandle, packet.data(), packet.size());
+                     storageInfo.read(mtpDataPacket);
+                     storageInfo.print();
+                 }});
+        mtpDeviceFunction();
+    }
+    close(fd);
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
new file mode 100644
index 0000000..3bd3be2
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_event_packet_fuzzer.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDevHandle.h>
+#include <MtpEventPacket.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace android;
+
+class MtpEventPacketFuzzer : MtpPacketFuzzerUtils {
+  public:
+    MtpEventPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                   sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpEventPacketFuzzer() { free(mUsbDevFsUrb); };
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void MtpEventPacketFuzzer::process() {
+    MtpEventPacket mtpEventPacket;
+    while (mFdp.remaining_bytes() > 0) {
+        auto mtpEventAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() { mtpEventPacket.allocate(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); },
+                [&]() { mtpEventPacket.reset(); },
+                [&]() { writeHandle(&mtpEventPacket, &mFdp); },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpEventPacket.sendRequest(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillFd(fd, &mFdp);
+                    struct usb_device* device = usb_device_new(mPath.c_str(), fd);
+                    mtpEventPacket.readResponse(device);
+                    usb_device_close(device);
+                },
+        });
+        mtpEventAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpEventPacketFuzzer mtpEventPacketFuzzer(data, size);
+    mtpEventPacketFuzzer.process();
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
index f578462..e886816 100644
--- a/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
+++ b/media/mtp/tests/MtpFuzzer/mtp_fuzzer.cpp
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
+#include <android-base/properties.h>
 #include <android-base/unique_fd.h>
+#include <fuzzer/FuzzedDataProvider.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
-
+#include <filesystem>
+#include <fstream>
 #include <string>
 
 #define LOG_TAG "MtpFuzzer"
@@ -32,38 +35,40 @@
 #include "MtpStorage.h"
 #include "MtpUtils.h"
 
-const char* storage_desc = "Fuzz Storage";
+constexpr int32_t kMinFiles = 0;
+constexpr int32_t kMaxFiles = 5;
+constexpr int32_t kMaxBytes = 128;
+constexpr float kMinDataSizeFactor = 0.8;
 // prefer tmpfs for file operations to avoid wearing out flash
 const char* storage_path = "/storage/fuzzer/0";
-const char* source_database = "srcdb/";
+const char* source_database = "/data/local/tmp/srcdb/";
+const std::string test_path = std::string(source_database) + "TestDir/";
+const std::string kPropertyKey = "sys.fuse.transcode_mtp";
 
 namespace android {
 class MtpMockServer {
-public:
-    std::unique_ptr<MtpMockHandle> mHandle;
-    std::unique_ptr<MtpStorage> mStorage;
-    std::unique_ptr<MtpMockDatabase> mDatabase;
-    std::unique_ptr<MtpServer> mMtp;
-    int mStorageId;
-
-    MtpMockServer(const char* storage_path) : mStorageId(0) {
-        bool ptp = false;
-        const char* manu = "Google";
-        const char* model = "Pixel 3XL";
-        const char* version = "1.0";
-        const char* serial = "ABDEF1231";
-
+  public:
+    MtpMockServer(const uint8_t* data, size_t size) : mFdp(data, size) {
         // This is unused in our harness
         int controlFd = -1;
 
         mHandle = std::make_unique<MtpMockHandle>();
-        mStorage = std::make_unique<MtpStorage>(mStorageId, storage_path, storage_desc, true,
-                                                0x200000000L);
+        mStorage = std::make_unique<MtpStorage>(
+                mFdp.ConsumeIntegral<uint32_t>() /* storageId */, storage_path,
+                mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* descriptor */,
+                mFdp.ConsumeBool() /* removable */,
+                mFdp.ConsumeIntegral<uint64_t>() /* maxFileSize */);
         mDatabase = std::make_unique<MtpMockDatabase>();
         mDatabase->addStorage(mStorage.get());
 
-        mMtp = std::make_unique<MtpServer>(mDatabase.get(), controlFd, ptp, manu, model, version,
-                                           serial);
+        init(data, size);
+
+        mMtp = std::make_unique<MtpServer>(
+                mDatabase.get(), controlFd, mFdp.ConsumeBool() /* ptp */,
+                mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* manu */,
+                mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* model */,
+                mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* version */,
+                mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* serial */);
         mMtp->addStorage(mStorage.get());
 
         // clear the old handle first, so we don't leak memory
@@ -71,7 +76,76 @@
         mMtp->mHandle = mHandle.get();
     }
 
-    void run() { mMtp->run(); }
+    void process() {
+        if (mFdp.ConsumeBool()) {
+            createDatabaseFromSourceDir(source_database, storage_path, MTP_PARENT_ROOT);
+        }
+
+        while (mFdp.remaining_bytes()) {
+            MtpStorage storage(mFdp.ConsumeIntegral<uint32_t>() /* id */,
+                               mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* filePath */,
+                               mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* description */,
+                               mFdp.ConsumeBool() /* removable */,
+                               mFdp.ConsumeIntegral<uint64_t>() /* maxFileSize */);
+
+            auto invokeMtpServerAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                    [&]() { mMtp->run(); },
+                    [&]() { mMtp->sendObjectAdded(mFdp.ConsumeIntegral<uint32_t>()); },
+                    [&]() { mMtp->sendObjectRemoved(mFdp.ConsumeIntegral<uint32_t>()); },
+                    [&]() { mMtp->sendObjectInfoChanged(mFdp.ConsumeIntegral<uint32_t>()); },
+                    [&]() { mMtp->sendDevicePropertyChanged(mFdp.ConsumeIntegral<uint16_t>()); },
+                    [&]() { mMtp->addStorage(&storage); },
+                    [&]() { mMtp->removeStorage(&storage); },
+            });
+
+            invokeMtpServerAPI();
+        }
+
+        std::filesystem::remove_all(source_database);
+    }
+
+  private:
+    void createFiles(std::string path, size_t fileCount) {
+        std::ofstream file;
+        for (size_t idx = 0; idx < fileCount; ++idx) {
+            file.open(path.append(std::to_string(idx)));
+            file.close();
+        }
+    }
+
+    void addPackets(const uint8_t* data, size_t size) {
+        size_t off = 0;
+        for (size_t i = 0; i < size; ++i) {
+            // A longer delimiter could be used, but this worked in practice
+            if (data[i] == '@') {
+                size_t pktsz = i - off;
+                if (pktsz > 0) {
+                    packet_t pkt = packet_t((unsigned char*)data + off, (unsigned char*)data + i);
+                    // insert into packet buffer
+                    mHandle->add_packet(pkt);
+                    off = i;
+                }
+            }
+        }
+    }
+
+    void init(const uint8_t* data, size_t size) {
+        std::vector<uint8_t> packetData = mFdp.ConsumeBytes<uint8_t>(
+                mFdp.ConsumeIntegralInRange<int32_t>(kMinDataSizeFactor * size, size));
+
+        // Packetize the input stream
+        addPackets(packetData.data(), packetData.size());
+
+        // Setting the property to true/false to randomly fuzz the PoC depended on it
+        base::SetProperty(kPropertyKey, mFdp.ConsumeBool() ? "true" : "false");
+
+        std::filesystem::create_directories(source_database);
+        if (mFdp.ConsumeBool()) {
+            std::filesystem::create_directories(test_path);
+            createFiles(test_path, mFdp.ConsumeIntegralInRange<size_t>(kMinFiles, kMaxFiles));
+        }
+        createFiles(source_database, mFdp.ConsumeIntegralInRange<size_t>(kMinFiles, kMaxFiles));
+    }
 
     int createDatabaseFromSourceDir(const char* fromPath, const char* toPath,
                                     MtpObjectHandle parentHandle) {
@@ -130,8 +204,14 @@
         closedir(dir);
         return ret;
     }
+
+    FuzzedDataProvider mFdp;
+    std::unique_ptr<MtpMockHandle> mHandle;
+    std::unique_ptr<MtpStorage> mStorage;
+    std::unique_ptr<MtpMockDatabase> mDatabase;
+    std::unique_ptr<MtpServer> mMtp;
 };
-}; // namespace android
+};  // namespace android
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) __attribute__((optnone)) {
     // reset our storage (from MtpUtils.h)
@@ -140,26 +220,9 @@
     android::makeFolder(storage_path);
 
     std::unique_ptr<android::MtpMockServer> mtp =
-            std::make_unique<android::MtpMockServer>(storage_path);
+            std::make_unique<android::MtpMockServer>(data, size);
+    mtp->process();
 
-    size_t off = 0;
-
-    // Packetize the input stream
-    for (size_t i = 0; i < size; i++) {
-        // A longer delimiter could be used, but this worked in practice
-        if (data[i] == '@') {
-            size_t pktsz = i - off;
-            if (pktsz > 0) {
-                packet_t pkt = packet_t((unsigned char*)data + off, (unsigned char*)data + i);
-                // insert into packet buffer
-                mtp->mHandle->add_packet(pkt);
-                off = i;
-            }
-        }
-    }
-
-    mtp->createDatabaseFromSourceDir(source_database, storage_path, MTP_PARENT_ROOT);
-    mtp->run();
-
+    std::filesystem::remove_all("/storage/fuzzer");
     return 0;
 }
diff --git a/media/mtp/tests/MtpFuzzer/mtp_handle_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_handle_fuzzer.cpp
new file mode 100644
index 0000000..7dcdc3f
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_handle_fuzzer.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <MtpDescriptors.h>
+#include <MtpFfsCompatHandle.h>
+#include <android-base/file.h>
+#include <fcntl.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <mtp.h>
+
+using namespace android;
+
+constexpr int32_t kMaxStringLength = 64;
+constexpr int32_t kMinAPICase = 0;
+constexpr int32_t kMaxMtpHandleAPI = 5;
+constexpr int32_t kMinBufferSize = 0;
+constexpr uint32_t kMaxMtpFileSize = 0xFFFFFFFF;
+constexpr float kDataSizeFactor = 0.1;
+
+const std::string kTempPath = "/data/local/tmp/";
+const std::string kFuzzerUsbDirPath = kTempPath + "usb-ffs";
+const std::string kFuzzerMtpPath = kFuzzerUsbDirPath + "/mtp";
+const std::string kFuzzerPtpPath = kFuzzerUsbDirPath + "/ptp";
+const std::string kFuzzerTestFile = kTempPath + "FuzzerTestDescriptorFile";
+const std::string kFuzzerMtpInputFile = kTempPath + "FuzzerMtpInputFile";
+const std::string kFuzzerMtpOutputFile = kTempPath + "FuzzerMtpOutputFile";
+
+const std::string kDeviceFilePaths[] = {FFS_MTP_EP0,    FFS_MTP_EP_IN, FFS_MTP_EP_INTR,
+                                        FFS_PTP_EP0,    FFS_PTP_EP_IN, FFS_PTP_EP_INTR,
+                                        FFS_MTP_EP_OUT, FFS_PTP_EP_OUT};
+
+class MtpFfsHandleFuzzer {
+  public:
+    MtpFfsHandleFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mDataSize = kDataSizeFactor * size;
+        createFiles();
+    };
+    void process();
+
+    ~MtpFfsHandleFuzzer() { removeFiles(); };
+
+  private:
+    FuzzedDataProvider mFdp;
+    void invokeWriteDescriptor();
+    void invokeMtpFfsHandle();
+    void createFiles();
+    void removeFiles();
+    void createDeviceFile(const char* file);
+    void writeDeviceFile(const char* file);
+    int32_t writeInputFile(int32_t fd);
+    uint32_t mDataSize = 0;
+};
+
+int32_t MtpFfsHandleFuzzer::writeInputFile(int32_t fd) {
+    uint32_t minFileSize = std::min((uint32_t)MTP_BUFFER_SIZE, mDataSize);
+    uint32_t maxFileSize = std::min(mDataSize, kMaxMtpFileSize);
+    std::vector<char> dataBuffer = mFdp.ConsumeBytes<char>(
+            mFdp.ConsumeIntegralInRange<uint32_t>(minFileSize, maxFileSize));
+    write(fd, dataBuffer.data(), dataBuffer.size());
+    lseek(fd, 0, SEEK_SET);
+    return dataBuffer.size();
+}
+
+void MtpFfsHandleFuzzer::createDeviceFile(const char* file) {
+    int32_t fd = open(file, O_CREAT | O_RDWR | O_NONBLOCK);
+    close(fd);
+}
+
+void MtpFfsHandleFuzzer::writeDeviceFile(const char* file) {
+    int32_t fd = open(file, O_RDWR | O_NONBLOCK);
+    writeInputFile(fd);
+    close(fd);
+}
+
+void MtpFfsHandleFuzzer::createFiles() {
+    mkdir(kFuzzerUsbDirPath.c_str(), 0755);
+    mkdir(kFuzzerMtpPath.c_str(), 0755);
+    mkdir(kFuzzerPtpPath.c_str(), 0755);
+
+    for (auto path : kDeviceFilePaths) {
+        createDeviceFile(path.c_str());
+    }
+
+    writeDeviceFile(FFS_MTP_EP_OUT);
+    writeDeviceFile(FFS_PTP_EP_OUT);
+}
+
+void MtpFfsHandleFuzzer::removeFiles() {
+    for (auto path : kDeviceFilePaths) {
+        remove(path.c_str());
+    }
+
+    rmdir(kFuzzerMtpPath.c_str());
+    rmdir(kFuzzerPtpPath.c_str());
+    rmdir(kFuzzerUsbDirPath.c_str());
+}
+
+void MtpFfsHandleFuzzer::invokeWriteDescriptor() {
+    while (mFdp.remaining_bytes() > 0) {
+        int32_t controlFd = mFdp.ConsumeBool()
+                                    ? -1 /* Invalid fd*/
+                                    : open(kFuzzerTestFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+        std::unique_ptr<MtpFfsHandle> handle(new MtpFfsHandle(controlFd));
+        handle->writeDescriptors(mFdp.ConsumeBool());
+        handle->close();
+        close(controlFd);
+        remove(kFuzzerTestFile.c_str());
+    }
+}
+
+void MtpFfsHandleFuzzer::invokeMtpFfsHandle() {
+    while (mFdp.remaining_bytes() > 0) {
+        int32_t controlFd = open(kFuzzerTestFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+        writeInputFile(controlFd);
+
+        std::unique_ptr<IMtpHandle> handle;
+        if (mFdp.ConsumeBool()) {
+            std::unique_ptr<IMtpHandle> mtpCompactHandle(new MtpFfsCompatHandle(controlFd));
+            handle = std::move(mtpCompactHandle);
+        } else {
+            std::unique_ptr<IMtpHandle> mtpHandle(new MtpFfsHandle(controlFd));
+            handle = std::move(mtpHandle);
+        }
+
+        int32_t mtpHandle = mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxMtpHandleAPI);
+        switch (mtpHandle) {
+            case 0: {
+                handle->start(mFdp.ConsumeBool());
+                break;
+            }
+            case 1: {
+                std::string data = mFdp.ConsumeRandomLengthString(MTP_BUFFER_SIZE);
+                handle->write(data.c_str(), data.length());
+                break;
+            }
+            case 2: {
+                int32_t bufferSize =
+                        mFdp.ConsumeIntegralInRange<size_t>(kMinBufferSize, MTP_BUFFER_SIZE);
+                uint8_t buffer[bufferSize + 1];
+                handle->read(buffer, bufferSize);
+                break;
+            }
+            case 3: {
+                mtp_file_range mfr;
+                mfr.fd = open(kFuzzerMtpInputFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+                mfr.length = writeInputFile(mfr.fd);
+                mfr.offset = 0; /* Offset point to the start of the file */
+                mfr.command = mFdp.ConsumeIntegral<uint16_t>();
+                mfr.transaction_id = mFdp.ConsumeIntegral<uint32_t>();
+                handle->sendFile(mfr);
+                close(mfr.fd);
+                remove(kFuzzerMtpInputFile.c_str());
+                break;
+            }
+            case 4: {
+                struct mtp_event event;
+                std::string dataValue = mFdp.ConsumeRandomLengthString(kMaxStringLength);
+                event.data = const_cast<char*>(dataValue.c_str());
+                event.length = dataValue.length();
+                handle->sendEvent(event);
+                break;
+            }
+            case 5:
+            default: {
+                mtp_file_range mfr;
+                mfr.fd = open(kFuzzerMtpOutputFile.c_str(), O_CREAT | O_RDWR | O_NONBLOCK);
+                mfr.offset = 0; /* Offset point to the start of the file */
+                mfr.length = kMaxMtpFileSize;
+                handle->receiveFile(mfr, mFdp.ConsumeBool());
+                close(mfr.fd);
+                remove(kFuzzerMtpOutputFile.c_str());
+                break;
+            }
+        }
+        handle->close();
+        close(controlFd);
+        remove(kFuzzerTestFile.c_str());
+    }
+}
+
+void MtpFfsHandleFuzzer::process() {
+    if (mFdp.ConsumeBool()) {
+        invokeMtpFfsHandle();
+    } else {
+        invokeWriteDescriptor();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpFfsHandleFuzzer mtpFfsHandleFuzzer(data, size);
+    mtpFfsHandleFuzzer.process();
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
new file mode 100644
index 0000000..6fc2a96
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_packet_fuzzer.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDevHandle.h>
+#include <MtpPacket.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace android;
+
+class MtpPacketFuzzer : MtpPacketFuzzerUtils {
+  public:
+    MtpPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                   sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpPacketFuzzer() { free(mUsbDevFsUrb); };
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void MtpPacketFuzzer::process() {
+    MtpPacket mtpPacket(mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)); /*bufferSize*/
+    while (mFdp.remaining_bytes() > 0) {
+        auto mtpPacketAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    mtpPacket.allocate(mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+                },
+                [&]() { mtpPacket.reset(); },
+                [&]() { mtpPacket.getContainerType(); },
+                [&]() { mtpPacket.getContainerCode(); },
+                [&]() { mtpPacket.dump(); },
+                [&]() { mtpPacket.getTransactionID(); },
+                [&]() {
+                    mtpPacket.setContainerCode(
+                            mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    mtpPacket.setTransactionID(
+                            mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    mtpPacket.getParameter(
+                            mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    mtpPacket.setParameter(
+                            mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize),
+                            mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+                },
+                [&]() {
+                    MtpPacket testMtpPacket(
+                            mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize));
+                    testMtpPacket.copyFrom(mtpPacket);
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpPacket.transfer(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+        });
+        mtpPacketAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpPacketFuzzer mtpPacketFuzzer(data, size);
+    mtpPacketFuzzer.process();
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
new file mode 100644
index 0000000..b4e659c
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_property_fuzzer.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDataPacket.h>
+#include <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <MtpProperty.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <utils/String16.h>
+
+using namespace android;
+
+constexpr uint16_t kFeasibleTypes[] = {
+        MTP_TYPE_UNDEFINED, MTP_TYPE_INT8,    MTP_TYPE_UINT8,  MTP_TYPE_INT16,   MTP_TYPE_UINT16,
+        MTP_TYPE_INT32,     MTP_TYPE_UINT32,  MTP_TYPE_INT64,  MTP_TYPE_UINT64,  MTP_TYPE_INT128,
+        MTP_TYPE_UINT128,   MTP_TYPE_AINT8,   MTP_TYPE_AUINT8, MTP_TYPE_AINT16,  MTP_TYPE_AUINT16,
+        MTP_TYPE_AINT32,    MTP_TYPE_AUINT32, MTP_TYPE_AINT64, MTP_TYPE_AUINT64, MTP_TYPE_AINT128,
+        MTP_TYPE_AUINT128,  MTP_TYPE_STR,
+};
+
+class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
+  public:
+    MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                    sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpPropertyFuzzer() { free(mUsbDevFsUrb); };
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void MtpPropertyFuzzer::process() {
+    MtpProperty* mtpProperty = nullptr;
+    if (mFdp.ConsumeBool()) {
+        mtpProperty = new MtpProperty();
+    } else {
+        uint16_t type = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral<uint16_t>()
+                                           : mFdp.PickValueInArray<uint16_t>(kFeasibleTypes);
+        mtpProperty = new MtpProperty(mFdp.ConsumeIntegral<uint16_t>(), type, mFdp.ConsumeBool(),
+                                      mFdp.ConsumeIntegral<uint16_t>());
+    }
+
+    while (mFdp.remaining_bytes() > 0) {
+        auto invokeMtpPropertyFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    MtpDataPacket mtpDataPacket;
+                    if (mFdp.ConsumeBool()) {
+                        mtpProperty->read(mtpDataPacket);
+
+                    } else {
+                        if (mFdp.ConsumeBool()) {
+#ifdef MTP_DEVICE
+                            android::IMtpHandle* h = new MtpDevHandle();
+                            h->start(mFdp.ConsumeBool());
+                            std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
+                            char* data = const_cast<char*>(text.c_str());
+                            h->read(static_cast<void*>(data), text.length());
+                            mtpDataPacket.write(h);
+                            h->close();
+                            delete h;
+#endif
+
+#ifdef MTP_HOST
+                            fillFilePath(&mFdp);
+                            int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                            fillUsbRequest(fd, &mFdp);
+                            mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                            mtpDataPacket.write(&mUsbRequest,
+                                                mFdp.PickValueInArray<UrbPacketDivisionMode>(
+                                                        kUrbPacketDivisionModes),
+                                                fd,
+                                                mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+                            usb_device_close(mUsbRequest.dev);
+#endif
+                        }
+
+                        if (mFdp.ConsumeBool()) {
+                            mtpProperty->write(mtpDataPacket);
+                        } else {
+                            mtpProperty->setCurrentValue(mtpDataPacket);
+                        }
+                    }
+                },
+                [&]() {
+                    char16_t* data = nullptr;
+                    std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
+                    android::String16 s(str.c_str());
+                    if (mFdp.ConsumeBool()) {
+                        data = const_cast<char16_t*>(s.string());
+                    }
+
+                    if (mFdp.ConsumeBool()) {
+                        mtpProperty->setDefaultValue(reinterpret_cast<uint16_t*>(data));
+                    } else if (mFdp.ConsumeBool()) {
+                        mtpProperty->setCurrentValue(reinterpret_cast<uint16_t*>(data));
+                    } else {
+                        mtpProperty->setCurrentValue(str.c_str());
+                    }
+                },
+                [&]() {
+                    mtpProperty->setFormRange(mFdp.ConsumeIntegral<int32_t>(),
+                                              mFdp.ConsumeIntegral<int32_t>(),
+                                              mFdp.ConsumeIntegral<int32_t>());
+                },
+                [&]() {
+                    std::vector<int32_t> init;
+                    for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize);
+                         ++idx) {
+                        init.push_back(mFdp.ConsumeIntegral<int32_t>());
+                    }
+                    mtpProperty->setFormEnum(init.data(), init.size());
+                },
+        });
+        invokeMtpPropertyFuzzer();
+    }
+
+    delete (mtpProperty);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpPropertyFuzzer mtpPropertyFuzzer(data, size);
+    mtpPropertyFuzzer.process();
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
new file mode 100644
index 0000000..19fbc5b
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_request_packet_fuzzer.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <MtpRequestPacket.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <fstream>
+
+using namespace android;
+
+std::string kMtpDevPath = "/dev/mtp_usb";
+constexpr int32_t kMaxBytes = 100000;
+
+class MtpRequestPacketFuzzer : MtpPacketFuzzerUtils {
+  public:
+    MtpRequestPacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                   sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpRequestPacketFuzzer() { free(mUsbDevFsUrb); };
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+    void makeFile(std::string s);
+};
+
+void MtpRequestPacketFuzzer::process() {
+    MtpRequestPacket mtpRequestPacket;
+    while (mFdp.remaining_bytes() > 0) {
+        auto mtpRequestAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    mtpRequestPacket.allocate(mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
+                },
+                [&]() { mtpRequestPacket.reset(); },
+                [&]() {
+                    MtpDevHandle handle;
+                    makeFile(kMtpDevPath);
+                    handle.start(mFdp.ConsumeBool());
+                    std::vector<uint8_t> data = mFdp.ConsumeBytes<uint8_t>(
+                            mFdp.ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
+                    handle.write(data.data(), data.size());
+                    mtpRequestPacket.read(&handle);
+                    handle.close();
+                    remove(kMtpDevPath.c_str());
+                },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpRequestPacket.write(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+        });
+        mtpRequestAPI();
+    }
+}
+
+void MtpRequestPacketFuzzer::makeFile(std::string s) {
+    std::ofstream out;
+    out.open(s, std::ios::binary | std::ofstream::trunc);
+    for (int32_t idx = 0; idx < mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize); ++idx) {
+        out << mFdp.ConsumeRandomLengthString(kMaxBytes) << "\n";
+    }
+    out.close();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpRequestPacketFuzzer mtpRequestPacketFuzzer(data, size);
+    mtpRequestPacketFuzzer.process();
+    return 0;
+}
diff --git a/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp b/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
new file mode 100644
index 0000000..697785f
--- /dev/null
+++ b/media/mtp/tests/MtpFuzzer/mtp_response_packet_fuzzer.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <MtpDevHandle.h>
+#include <MtpPacketFuzzerUtils.h>
+#include <MtpResponsePacket.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using namespace android;
+
+class MtpResponsePacketFuzzer : MtpPacketFuzzerUtils {
+  public:
+    MtpResponsePacketFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+        mUsbDevFsUrb = (struct usbdevfs_urb*)malloc(sizeof(struct usbdevfs_urb) +
+                                                   sizeof(struct usbdevfs_iso_packet_desc));
+    };
+    ~MtpResponsePacketFuzzer() { free(mUsbDevFsUrb); };
+    void process();
+
+  private:
+    FuzzedDataProvider mFdp;
+};
+
+void MtpResponsePacketFuzzer::process() {
+    MtpResponsePacket mtpResponsePacket;
+    while (mFdp.remaining_bytes() > 0) {
+        auto mtpResponseAPI = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    mtpResponsePacket.allocate(
+                            mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize)); /*size*/
+                },
+                [&]() { mtpResponsePacket.reset(); },
+                [&]() { writeHandle(&mtpResponsePacket, &mFdp); },
+                [&]() {
+                    fillFilePath(&mFdp);
+                    int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
+                    fillUsbRequest(fd, &mFdp);
+                    mUsbRequest.dev = usb_device_new(mPath.c_str(), fd);
+                    mtpResponsePacket.read(&mUsbRequest);
+                    usb_device_close(mUsbRequest.dev);
+                },
+        });
+        mtpResponseAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    MtpResponsePacketFuzzer mtpResponsePacketFuzzer(data, size);
+    mtpResponsePacketFuzzer.process();
+    return 0;
+}
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index ddc71db..fded4f5 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -52,6 +52,9 @@
     symbol_file: "libmediandk.map.txt",
     first_version: "21",
     unversioned_until: "current",
+    export_header_libs: [
+        "libmediandk_headers",
+    ],
 }
 
 ndk_headers {
@@ -167,7 +170,7 @@
     stubs: {
         symbol_file: "libmediandk.map.txt",
         versions: ["29"],
-    }
+    },
 }
 
 cc_library {
diff --git a/media/ndk/NdkMediaDrm.cpp b/media/ndk/NdkMediaDrm.cpp
index f4674de..0df7636 100644
--- a/media/ndk/NdkMediaDrm.cpp
+++ b/media/ndk/NdkMediaDrm.cpp
@@ -253,7 +253,7 @@
 }
 
 static sp<IDrm> CreateDrm() {
-    return DrmUtils::MakeDrm();
+    return DrmUtils::MakeDrm(IDRM_NDK);
 }
 
 
@@ -758,6 +758,9 @@
 EXPORT
 media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *mObj,
         const char *propertyName, const uint8_t *value, size_t valueSize) {
+    if (!mObj || mObj->mDrm == NULL) {
+        return AMEDIA_ERROR_INVALID_OBJECT;
+    }
 
     Vector<uint8_t> byteArray;
     byteArray.appendArray(value, valueSize);
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 923453a..a95e874 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -147,38 +147,80 @@
 
 EXPORT
 bool AMediaFormat_getInt32(AMediaFormat* format, const char *name, int32_t *out) {
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     return format->mFormat->findInt32(name, out);
 }
 
 EXPORT
 bool AMediaFormat_getInt64(AMediaFormat* format, const char *name, int64_t *out) {
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     return format->mFormat->findInt64(name, out);
 }
 
 EXPORT
 bool AMediaFormat_getFloat(AMediaFormat* format, const char *name, float *out) {
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     return format->mFormat->findFloat(name, out);
 }
 
 EXPORT
 bool AMediaFormat_getDouble(AMediaFormat* format, const char *name, double *out) {
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     return format->mFormat->findDouble(name, out);
 }
 
 EXPORT
 bool AMediaFormat_getSize(AMediaFormat* format, const char *name, size_t *out) {
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     return format->mFormat->findSize(name, out);
 }
 
 EXPORT
 bool AMediaFormat_getRect(AMediaFormat* format, const char *name,
                           int32_t *left, int32_t *top, int32_t *right, int32_t *bottom) {
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     return format->mFormat->findRect(name, left, top, right, bottom);
 }
 
 EXPORT
 bool AMediaFormat_getBuffer(AMediaFormat* format, const char *name, void** data, size_t *outsize) {
     sp<ABuffer> buf;
+    if (format == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     if (format->mFormat->findBuffer(name, &buf)) {
         *data = buf->data() + buf->offset();
         *outsize = buf->size();
@@ -189,7 +231,12 @@
 
 EXPORT
 bool AMediaFormat_getString(AMediaFormat* mData, const char *name, const char **out) {
-
+    if (mData == nullptr) {
+        return false;
+    }
+    if (name == nullptr) {
+        return false;
+    }
     for (size_t i = 0; i < mData->mStringCache.size(); i++) {
         if (strcmp(mData->mStringCache.keyAt(i).string(), name) == 0) {
             mData->mStringCache.removeItemsAt(i, 1);
@@ -212,43 +259,91 @@
 
 EXPORT
 void AMediaFormat_setInt32(AMediaFormat* format, const char *name, int32_t value) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     format->mFormat->setInt32(name, value);
 }
 
 EXPORT
 void AMediaFormat_setInt64(AMediaFormat* format, const char *name, int64_t value) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     format->mFormat->setInt64(name, value);
 }
 
 EXPORT
 void AMediaFormat_setFloat(AMediaFormat* format, const char* name, float value) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     format->mFormat->setFloat(name, value);
 }
 
 EXPORT
 void AMediaFormat_setDouble(AMediaFormat* format, const char* name, double value) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     format->mFormat->setDouble(name, value);
 }
 
 EXPORT
 void AMediaFormat_setSize(AMediaFormat* format, const char* name, size_t value) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     format->mFormat->setSize(name, value);
 }
 
 EXPORT
 void AMediaFormat_setRect(AMediaFormat* format, const char *name,
                           int32_t left, int32_t top, int32_t right, int32_t bottom) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     format->mFormat->setRect(name, left, top, right, bottom);
 }
 
 EXPORT
 void AMediaFormat_setString(AMediaFormat* format, const char* name, const char* value) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     // AMessage::setString() makes a copy of the string
     format->mFormat->setString(name, value, strlen(value));
 }
 
 EXPORT
 void AMediaFormat_setBuffer(AMediaFormat* format, const char* name, const void* data, size_t size) {
+    if (format == nullptr) {
+        return;
+    }
+    if (name == nullptr) {
+        return;
+    }
     // the ABuffer(void*, size_t) constructor doesn't take ownership of the data, so create
     // a new buffer and copy the data into it
     sp<ABuffer> buf = new ABuffer(size);
diff --git a/media/ndk/NdkMediaMuxer.cpp b/media/ndk/NdkMediaMuxer.cpp
index 1965e62..9d62884 100644
--- a/media/ndk/NdkMediaMuxer.cpp
+++ b/media/ndk/NdkMediaMuxer.cpp
@@ -46,7 +46,7 @@
     if (mData == nullptr) {
         return nullptr;
     }
-    mData->mImpl = new (std::nothrow) MediaMuxer(fd, (android::MediaMuxer::OutputFormat)format);
+    mData->mImpl = MediaMuxer::create(fd, (MediaMuxer::OutputFormat)format);
     if (mData->mImpl == nullptr) {
         delete mData;
         return nullptr;
diff --git a/media/ndk/include/media/NdkMediaDrm.h b/media/ndk/include/media/NdkMediaDrm.h
index 4eca3d7..8044140 100644
--- a/media/ndk/include/media/NdkMediaDrm.h
+++ b/media/ndk/include/media/NdkMediaDrm.h
@@ -261,8 +261,8 @@
 /**
  * Open a new session with the MediaDrm object.  A session ID is returned.
  *
- * Returns MEDIADRM_NOT_PROVISIONED_ERROR if provisioning is needed.
- * Returns MEDIADRM_RESOURCE_BUSY_ERROR if required resources are in use.
+ * Returns AMEDIA_DRM_NOT_PROVISIONED if provisioning is needed.
+ * Returns AMEDIA_DRM_RESOURCE_BUSY if required resources are in use.
  *
  * Available since API level 21.
  */
@@ -327,7 +327,7 @@
  *   2. keyRequestSize will be set to the size of the request
  *   If this does not return AMEDIA_OK, value of these parameters should not be used.
  *
- * Returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
+ * Returns AMEDIA_DRM_NOT_PROVISIONED if reprovisioning is needed, due to a
  * problem with the device certificate.
  *
  * Available since API level 21.
@@ -390,7 +390,7 @@
  *   4. keyRequestType will be set to the key request type. Passing in NULL means
 *       you don't need it to be reported.
  *
- * Returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
+ * Returns AMEDIA_DRM_NOT_PROVISIONED if reprovisioning is needed, due to a
  * problem with the device certificate.
  *
  * Available since API level 33.
@@ -457,7 +457,7 @@
  * On entry, numPairs should be set by the caller to the maximum number of pairs
  * that can be returned (the size of the array).  On exit, numPairs will be set
  * to the number of entries written to the array.  If the number of {key, value} pairs
- * to be returned is greater than *numPairs, MEDIADRM_SHORT_BUFFER will be returned
+ * to be returned is greater than *numPairs, AMEDIA_DRM_SHORT_BUFFER will be returned
  * and numPairs will be set to the number of pairs available.
  *
  * Available since API level 21.
@@ -495,7 +495,7 @@
  *   DRM engine plugin.
  * responseSize is the length of the provisioning response in bytes.
  *
- * Returns MEDIADRM_DEVICE_REVOKED_ERROR if the response indicates that the
+ * Returns AMEDIA_DRM_DEVICE_REVOKED if the response indicates that the
  * server rejected the request
  *
  * Available since API level 21.
@@ -522,7 +522,7 @@
  * numSecureStops is set by the caller to the maximum number of secure stops to
  * return.  On exit, *numSecureStops will be set to the number actually returned.
  * If *numSecureStops is too small for the number of secure stops available,
- * MEDIADRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the
+ * AMEDIA_DRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the
  * number required.
  *
  * Available since API level 21.
@@ -657,7 +657,7 @@
  * Generate a signature using the specified macAlgorithm over the message data
  * referenced by message of size messageSize and store the signature in the
  * buffer referenced signature of max size *signatureSize.  If the buffer is not
- * large enough to hold the signature, MEDIADRM_SHORT_BUFFER is returned and
+ * large enough to hold the signature, AMEDIA_DRM_SHORT_BUFFER is returned and
  * *signatureSize is set to the buffer size required.  The key to use is identified
  * by the 16 byte keyId.  The key must have been loaded into the session using
  * provideKeyResponse.
@@ -670,7 +670,7 @@
 
 /*
  * Perform a signature verification using the specified macAlgorithm over the message
- * data referenced by the message parameter of size messageSize. Returns MEDIADRM_OK
+ * data referenced by the message parameter of size messageSize. Returns AMEDIA_OK
  * if the signature matches, otherwise MEDAIDRM_VERIFY_FAILED is returned. The key to
  * use is identified by the 16 byte keyId.  The key must have been loaded into the
  * session using provideKeyResponse.
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index c8faced..c0eea63 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -181,11 +181,11 @@
     AMediaCodecCryptoInfo_setPattern; # introduced=24
     AMediaCodec_configure;
     AMediaCodec_createCodecByName;
-    AMediaCodec_createCodecByNameForClient; # apex # introduced=31
+    AMediaCodec_createCodecByNameForClient; # systemapi # introduced=31
     AMediaCodec_createDecoderByType;
-    AMediaCodec_createDecoderByTypeForClient; # apex # introduced=31
+    AMediaCodec_createDecoderByTypeForClient; # systemapi # introduced=31
     AMediaCodec_createEncoderByType;
-    AMediaCodec_createEncoderByTypeForClient; # apex # introduced=31
+    AMediaCodec_createEncoderByTypeForClient; # systemapi # introduced=31
     AMediaCodec_delete;
     AMediaCodec_dequeueInputBuffer;
     AMediaCodec_dequeueOutputBuffer;
diff --git a/media/ndk/tests/NdkMediaFormat_test.cpp b/media/ndk/tests/NdkMediaFormat_test.cpp
index 668d0a4..18690b8 100644
--- a/media/ndk/tests/NdkMediaFormat_test.cpp
+++ b/media/ndk/tests/NdkMediaFormat_test.cpp
@@ -51,6 +51,13 @@
    EXPECT_FALSE(AMediaFormat_getInt64(fmt1, "five", &i64));
    EXPECT_EQ(i32, 5);
 
+   // verify detecting some bad parameters.
+   AMediaFormat_setInt32(nullptr, "whatever", 6);
+   AMediaFormat_setInt32(fmt1, nullptr, 6);
+
+   EXPECT_FALSE(AMediaFormat_getInt32(nullptr, "whatever", &i32));
+   EXPECT_FALSE(AMediaFormat_getInt32(fmt1, nullptr, &i32));
+
    AMediaFormat_delete(fmt1);
 }
 
@@ -67,6 +74,13 @@
    EXPECT_FALSE(AMediaFormat_getInt64(fmt1, "five", &i64));
    EXPECT_EQ(i64, -1);
 
+   // verify detecting some bad parameters.
+   AMediaFormat_setInt64(nullptr, "whatever", 6);
+   AMediaFormat_setInt64(fmt1, nullptr, 6);
+
+   EXPECT_FALSE(AMediaFormat_getInt64(nullptr, "whatever", &i64));
+   EXPECT_FALSE(AMediaFormat_getInt64(fmt1, nullptr, &i64));
+
    AMediaFormat_delete(fmt1);
 }
 
@@ -80,6 +94,13 @@
    EXPECT_TRUE(AMediaFormat_getSize(fmt1, "medium", &size));
    EXPECT_EQ(size, 10);
 
+   // verify detecting some bad parameters.
+   AMediaFormat_setSize(nullptr, "whatever", 6);
+   AMediaFormat_setSize(fmt1, nullptr, 6);
+
+   EXPECT_FALSE(AMediaFormat_getSize(nullptr, "whatever", &size));
+   EXPECT_FALSE(AMediaFormat_getSize(fmt1, nullptr, &size));
+
    AMediaFormat_delete(fmt1);
 }
 
@@ -90,6 +111,14 @@
    AMediaFormat_setFloat(fmt1, "ship", 0.5);
    EXPECT_TRUE(AMediaFormat_getFloat(fmt1, "boat", &f));
    EXPECT_EQ(f, 1.5);
+
+   // verify detecting some bad parameters.
+   AMediaFormat_setFloat(nullptr, "whatever", 1.5);
+   AMediaFormat_setFloat(fmt1, nullptr, 1.5);
+
+   EXPECT_FALSE(AMediaFormat_getFloat(nullptr, "whatever", &f));
+   EXPECT_FALSE(AMediaFormat_getFloat(fmt1, nullptr, &f));
+
    AMediaFormat_delete(fmt1);
 }
 
@@ -100,6 +129,14 @@
    AMediaFormat_setDouble(fmt1, "dip", 0.5);
    EXPECT_TRUE(AMediaFormat_getDouble(fmt1, "trouble", &d));
    EXPECT_EQ(d, 100.5);
+
+   // verify detecting some bad parameters.
+   AMediaFormat_setDouble(nullptr, "whatever", 1.5);
+   AMediaFormat_setDouble(fmt1, nullptr, 1.5);
+
+   EXPECT_FALSE(AMediaFormat_getDouble(nullptr, "whatever", &d));
+   EXPECT_FALSE(AMediaFormat_getDouble(fmt1, nullptr, &d));
+
    AMediaFormat_delete(fmt1);
 }
 
@@ -111,8 +148,16 @@
    AMediaFormat_setString(fmt1, "stringtheory", content);
    EXPECT_TRUE(AMediaFormat_getString(fmt1, "stringtheory", &out));
    EXPECT_NE(out, nullptr);
+   EXPECT_NE(out, content);     // should not be the original
    EXPECT_EQ(strcmp(out,content), 0);
 
+   // verify detecting some bad parameters.
+   AMediaFormat_setString(nullptr, "whatever", content);
+   AMediaFormat_setString(fmt1, nullptr, content);
+
+   EXPECT_FALSE(AMediaFormat_getString(nullptr, "whatever", &out));
+   EXPECT_FALSE(AMediaFormat_getString(fmt1, nullptr, &out));
+
    AMediaFormat_delete(fmt1);
 }
 
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
index 21ba957..7fd2752 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/MuxerTest.java
@@ -60,14 +60,12 @@
     private static final String mStatsFile =
             mContext.getExternalFilesDir(null) + "/Muxer." + System.currentTimeMillis() + ".csv";
     private static final String TAG = "MuxerTest";
-    private static final Map<String, Integer> mMapFormat = new Hashtable<String, Integer>() {
-        {
-            put("mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
-            put("webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM);
-            put("3gpp", MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP);
-            put("ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
-        }
-    };
+    private static final Map<String, Integer> mMapFormat = Map.of(
+            "mp4", MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
+            "webm", MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM,
+            "3gpp", MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP,
+            "ogg", MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG);
+
     private String mInputFileName;
     private String mFormat;
 
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
index 043bc9e..a0628fa 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeDecoder.cpp
@@ -19,6 +19,7 @@
 
 #include <jni.h>
 #include <fstream>
+#include <memory>
 #include <stdio.h>
 #include <string.h>
 #include <sys/stat.h>
@@ -42,7 +43,7 @@
         return -1;
     }
 
-    Decoder *decoder = new Decoder();
+    std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
     Extractor *extractor = decoder->getExtractor();
     if (!extractor) {
         ALOGE("Extractor creation failed");
@@ -125,6 +126,5 @@
         inputFp = nullptr;
     }
     extractor->deInitExtractor();
-    delete decoder;
     return 0;
 }
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
index a5ef5b8..a297526 100644
--- a/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/cpp/NativeMuxer.cpp
@@ -19,6 +19,7 @@
 
 #include <jni.h>
 #include <fstream>
+#include <memory>
 #include <string>
 #include <sys/stat.h>
 
@@ -47,7 +48,7 @@
         return MUXER_OUTPUT_FORMAT_INVALID;
     }
 
-    Muxer *muxerObj = new Muxer();
+    std::unique_ptr<Muxer> muxerObj(new (std::nothrow) Muxer());
     Extractor *extractor = muxerObj->getExtractor();
     if (!extractor) {
         ALOGE("Extractor creation failed");
@@ -159,7 +160,6 @@
     }
     env->ReleaseStringUTFChars(jFormat, fmt);
     extractor->deInitExtractor();
-    delete muxerObj;
 
     return 0;
 }
diff --git a/media/tests/benchmark/src/native/common/BenchmarkCommon.h b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
index 40a8c9e..ba3e81a 100644
--- a/media/tests/benchmark/src/native/common/BenchmarkCommon.h
+++ b/media/tests/benchmark/src/native/common/BenchmarkCommon.h
@@ -50,7 +50,7 @@
         {
             lock_guard<mutex> lock(mMutex);
             needsNotify = mQueue.empty();
-            mQueue.push(move(elem));
+            mQueue.push(std::move(elem));
         }
         if (needsNotify) mQueueNotEmptyCondition.notify_one();
     }
diff --git a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
index ca79881..5b7a471 100644
--- a/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
+++ b/media/tests/benchmark/src/native/encoder/C2Encoder.cpp
@@ -17,11 +17,13 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "C2Encoder"
 
+#include <memory>
+
 #include "C2Encoder.h"
 
 int32_t C2Encoder::createCodec2Component(string compName, AMediaFormat *format) {
     ALOGV("In %s", __func__);
-    mListener.reset(new CodecListener(
+    mListener.reset(new (std::nothrow) CodecListener(
             [this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
     if (!mListener) return -1;
 
@@ -125,7 +127,7 @@
     }
     int32_t numFrames = (inputBufferSize + frameSize - 1) / frameSize;
     // Temporary buffer to read data from the input file
-    char *data = (char *)malloc(frameSize);
+    std::unique_ptr<char[]> data(new (std::nothrow) char[frameSize]);
     if (!data) {
         ALOGE("Insufficient memory to read from input file");
         return -1;
@@ -169,7 +171,7 @@
         if (inputBufferSize - offset < frameSize) {
             frameSize = inputBufferSize - offset;
         }
-        eleStream.read(data, frameSize);
+        eleStream.read(data.get(), frameSize);
         if (eleStream.gcount() != frameSize) {
             ALOGE("read() from file failed. Incorrect bytes read");
             return -1;
@@ -191,8 +193,8 @@
                     return view.error();
                 }
 
-                memcpy(view.base(), data, frameSize);
-                work->input.buffers.emplace_back(new LinearBuffer(block));
+                memcpy(view.base(), data.get(), frameSize);
+                work->input.buffers.emplace_back(new (std::nothrow) LinearBuffer(block));
             } else {
                 std::shared_ptr<C2GraphicBlock> block;
                 status = mGraphicPool->fetchGraphicBlock(
@@ -211,16 +213,16 @@
                 uint8_t *pY = view.data()[C2PlanarLayout::PLANE_Y];
                 uint8_t *pU = view.data()[C2PlanarLayout::PLANE_U];
                 uint8_t *pV = view.data()[C2PlanarLayout::PLANE_V];
-                memcpy(pY, data, mWidth * mHeight);
-                memcpy(pU, data + mWidth * mHeight, (mWidth * mHeight >> 2));
-                memcpy(pV, data + (mWidth * mHeight * 5 >> 2), mWidth * mHeight >> 2);
-                work->input.buffers.emplace_back(new GraphicBuffer(block));
+                memcpy(pY, data.get(), mWidth * mHeight);
+                memcpy(pU, data.get() + mWidth * mHeight, (mWidth * mHeight >> 2));
+                memcpy(pV, data.get() + (mWidth * mHeight * 5 >> 2), mWidth * mHeight >> 2);
+                work->input.buffers.emplace_back(new (std::nothrow) GraphicBuffer(block));
             }
             mStats->addFrameSize(frameSize);
         }
 
         work->worklets.clear();
-        work->worklets.emplace_back(new C2Worklet);
+        work->worklets.emplace_back(new (std::nothrow) C2Worklet);
 
         std::list<std::unique_ptr<C2Work>> items;
         items.push_back(std::move(work));
@@ -234,7 +236,6 @@
         numFrames--;
         mNumInputFrame++;
     }
-    free(data);
     return status;
 }
 
diff --git a/media/tests/benchmark/tests/C2DecoderTest.cpp b/media/tests/benchmark/tests/C2DecoderTest.cpp
index 85dcbc1..6e4d9e1 100644
--- a/media/tests/benchmark/tests/C2DecoderTest.cpp
+++ b/media/tests/benchmark/tests/C2DecoderTest.cpp
@@ -20,6 +20,7 @@
 #include <fstream>
 #include <iostream>
 #include <limits>
+#include <memory>
 
 #include "BenchmarkTestEnvironment.h"
 #include "C2Decoder.h"
@@ -50,7 +51,7 @@
 };
 
 void C2DecoderTest::setupC2DecoderTest() {
-    mDecoder = new C2Decoder();
+    mDecoder = new (std::nothrow) C2Decoder();
     ASSERT_NE(mDecoder, nullptr) << "C2Decoder creation failed";
 
     int32_t status = mDecoder->setupCodec2();
@@ -66,7 +67,7 @@
     FILE *inputFp = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
 
-    Extractor *extractor = new Extractor();
+    std::unique_ptr<Extractor> extractor(new (std::nothrow) Extractor());
     ASSERT_NE(extractor, nullptr) << "Extractor creation failed";
 
     // Read file properties
@@ -85,7 +86,7 @@
         int32_t status = extractor->setupTrackFormat(curTrack);
         ASSERT_EQ(status, 0) << "Track Format invalid";
 
-        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+        std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[fileSize]);
         ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
 
         vector<AMediaCodecBufferInfo> frameInfo;
@@ -100,7 +101,7 @@
             // copy the meta data and buffer to be passed to decoder
             ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
 
-            memcpy(inputBuffer + inputBufferOffset, csdBuffer, info.size);
+            memcpy(inputBuffer.get() + inputBufferOffset, csdBuffer, info.size);
             frameInfo.push_back(info);
             inputBufferOffset += info.size;
             idx++;
@@ -113,7 +114,7 @@
             // copy the meta data and buffer to be passed to decoder
             ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
 
-            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
             frameInfo.push_back(info);
             inputBufferOffset += info.size;
         }
@@ -127,7 +128,7 @@
                 ASSERT_EQ(status, 0) << "Create component failed for " << codecName;
 
                 // Send the inputs to C2 Decoder and wait till all buffers are returned.
-                status = mDecoder->decodeFrames(inputBuffer, frameInfo);
+                status = mDecoder->decodeFrames(inputBuffer.get(), frameInfo);
                 ASSERT_EQ(status, 0) << "Decoder failed for " << codecName;
 
                 mDecoder->waitOnInputConsumption();
@@ -141,10 +142,8 @@
                 mDecoder->resetDecoder();
             }
         }
-        free(inputBuffer);
         fclose(inputFp);
         extractor->deInitExtractor();
-        delete extractor;
         delete mDecoder;
         mDecoder = nullptr;
     }
@@ -174,7 +173,7 @@
                           make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
 
 int main(int argc, char **argv) {
-    gEnv = new BenchmarkTestEnvironment();
+    gEnv = new (std::nothrow) BenchmarkTestEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/C2EncoderTest.cpp b/media/tests/benchmark/tests/C2EncoderTest.cpp
index b18d856..dfbe496 100644
--- a/media/tests/benchmark/tests/C2EncoderTest.cpp
+++ b/media/tests/benchmark/tests/C2EncoderTest.cpp
@@ -20,6 +20,7 @@
 #include <fstream>
 #include <iostream>
 #include <limits>
+#include <memory>
 
 #include "BenchmarkTestEnvironment.h"
 #include "C2Encoder.h"
@@ -50,7 +51,7 @@
 };
 
 void C2EncoderTest::setupC2EncoderTest() {
-    mEncoder = new C2Encoder();
+    mEncoder = new (std::nothrow) C2Encoder();
     ASSERT_NE(mEncoder, nullptr) << "C2Encoder creation failed";
 
     int32_t status = mEncoder->setupCodec2();
@@ -66,7 +67,7 @@
     FILE *inputFp = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(inputFp, nullptr) << "Unable to open input file for reading";
 
-    Decoder *decoder = new Decoder();
+    std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
     ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
 
     Extractor *extractor = decoder->getExtractor();
@@ -88,7 +89,7 @@
         int32_t status = extractor->setupTrackFormat(curTrack);
         ASSERT_EQ(status, 0) << "Track Format invalid";
 
-        uint8_t *inputBuffer = (uint8_t *)malloc(fileSize);
+        std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[fileSize]);
         ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
 
         vector<AMediaCodecBufferInfo> frameInfo;
@@ -102,7 +103,7 @@
             // copy the meta data and buffer to be passed to decoder
             ASSERT_LE(inputBufferOffset + info.size, fileSize) << "Memory allocated not sufficient";
 
-            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
             frameInfo.push_back(info);
             inputBufferOffset += info.size;
         }
@@ -114,7 +115,8 @@
                                   << " for dumping decoder's output";
 
         decoder->setupDecoder();
-        status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+        status = decoder->decode(inputBuffer.get(), frameInfo, decName,
+                                 false /*asyncMode */, outFp);
         ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
 
         // Encode the given input stream for all C2 codecs supported by device
@@ -149,11 +151,9 @@
         // Destroy the decoder for the given input
         decoder->deInitCodec();
         decoder->resetDecoder();
-        free(inputBuffer);
     }
     fclose(inputFp);
     extractor->deInitExtractor();
-    delete decoder;
     delete mEncoder;
     mEncoder = nullptr;
 }
@@ -176,7 +176,7 @@
                           make_pair("crowd_1920x1080_25fps_4000kbps_h265.mkv", "hevc")));
 
 int main(int argc, char **argv) {
-    gEnv = new BenchmarkTestEnvironment();
+    gEnv = new (std::nothrow) BenchmarkTestEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/DecoderTest.cpp b/media/tests/benchmark/tests/DecoderTest.cpp
index 3666724..b363df3 100644
--- a/media/tests/benchmark/tests/DecoderTest.cpp
+++ b/media/tests/benchmark/tests/DecoderTest.cpp
@@ -20,6 +20,7 @@
 #include <fstream>
 #include <iostream>
 #include <limits>
+#include <memory>
 
 #include <android/binder_process.h>
 
@@ -38,7 +39,7 @@
     FILE *inputFp = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
 
-    Decoder *decoder = new Decoder();
+    std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
     ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
 
     Extractor *extractor = decoder->getExtractor();
@@ -57,7 +58,7 @@
         int32_t status = extractor->setupTrackFormat(curTrack);
         ASSERT_EQ(status, 0) << "Track Format invalid";
 
-        uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+        std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[kMaxBufferSize]);
         ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
 
         vector<AMediaCodecBufferInfo> frameInfo;
@@ -72,7 +73,7 @@
             ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
                     << "Memory allocated not sufficient";
 
-            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
             frameInfo.push_back(info);
             inputBufferOffset += info.size;
         }
@@ -80,7 +81,7 @@
         string codecName = get<1>(params);
         bool asyncMode = get<2>(params);
         decoder->setupDecoder();
-        status = decoder->decode(inputBuffer, frameInfo, codecName, asyncMode);
+        status = decoder->decode(inputBuffer.get(), frameInfo, codecName, asyncMode);
         ASSERT_EQ(status, AMEDIA_OK) << "Decoder failed for " << codecName;
 
         decoder->deInitCodec();
@@ -88,12 +89,10 @@
         string inputReference = get<0>(params);
         decoder->dumpStatistics(inputReference, codecName, (asyncMode ? "async" : "sync"),
                                 gEnv->getStatsFile());
-        free(inputBuffer);
         decoder->resetDecoder();
     }
     fclose(inputFp);
     extractor->deInitExtractor();
-    delete decoder;
 }
 
 // TODO: (b/140549596)
@@ -178,7 +177,7 @@
 
 int main(int argc, char **argv) {
     ABinderProcess_startThreadPool();
-    gEnv = new BenchmarkTestEnvironment();
+    gEnv = new (std::nothrow) BenchmarkTestEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
@@ -190,4 +189,4 @@
         ALOGV("Decoder Test result = %d\n", status);
     }
     return status;
-}
\ No newline at end of file
+}
diff --git a/media/tests/benchmark/tests/EncoderTest.cpp b/media/tests/benchmark/tests/EncoderTest.cpp
index 7e1681d..6703b99 100644
--- a/media/tests/benchmark/tests/EncoderTest.cpp
+++ b/media/tests/benchmark/tests/EncoderTest.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "encoderTest"
 
 #include <fstream>
+#include <memory>
 
 #include "BenchmarkTestEnvironment.h"
 #include "Decoder.h"
@@ -39,7 +40,7 @@
     FILE *inputFp = fopen(inputFile.c_str(), "rb");
     ASSERT_NE(inputFp, nullptr) << "Unable to open " << inputFile << " file for reading";
 
-    Decoder *decoder = new Decoder();
+    std::unique_ptr<Decoder> decoder(new (std::nothrow) Decoder());
     ASSERT_NE(decoder, nullptr) << "Decoder creation failed";
 
     Extractor *extractor = decoder->getExtractor();
@@ -54,14 +55,14 @@
     int32_t trackCount = extractor->initExtractor(fd, fileSize);
     ASSERT_GT(trackCount, 0) << "initExtractor failed";
 
-    Encoder *encoder = new Encoder();
+    std::unique_ptr<Encoder> encoder(new (std::nothrow) Encoder());
     ASSERT_NE(encoder, nullptr) << "Decoder creation failed";
 
     for (int curTrack = 0; curTrack < trackCount; curTrack++) {
         int32_t status = extractor->setupTrackFormat(curTrack);
         ASSERT_EQ(status, 0) << "Track Format invalid";
 
-        uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+        std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[kMaxBufferSize]);
         ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
 
         vector<AMediaCodecBufferInfo> frameInfo;
@@ -76,7 +77,7 @@
             ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
                     << "Memory allocated not sufficient";
 
-            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
             frameInfo.push_back(info);
             inputBufferOffset += info.size;
         }
@@ -88,7 +89,7 @@
                                   << " for dumping decoder's output";
 
         decoder->setupDecoder();
-        status = decoder->decode(inputBuffer, frameInfo, decName, false /*asyncMode */, outFp);
+        status = decoder->decode(inputBuffer.get(), frameInfo, decName, false /*asyncMode */, outFp);
         ASSERT_EQ(status, AMEDIA_OK) << "Decode returned error : " << status;
         AMediaFormat *decoderFormat = decoder->getFormat();
 
@@ -154,13 +155,10 @@
         }
         encoder->resetEncoder();
         decoder->deInitCodec();
-        free(inputBuffer);
         decoder->resetDecoder();
     }
-    delete encoder;
     fclose(inputFp);
     extractor->deInitExtractor();
-    delete decoder;
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -220,7 +218,7 @@
                                             "c2.android.hevc.encoder", true)));
 
 int main(int argc, char **argv) {
-    gEnv = new BenchmarkTestEnvironment();
+    gEnv = new (std::nothrow) BenchmarkTestEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/ExtractorTest.cpp b/media/tests/benchmark/tests/ExtractorTest.cpp
index 27ee9ba..35fb465 100644
--- a/media/tests/benchmark/tests/ExtractorTest.cpp
+++ b/media/tests/benchmark/tests/ExtractorTest.cpp
@@ -17,6 +17,8 @@
 //#define LOG_NDEBUG 0
 #define LOG_TAG "extractorTest"
 
+#include <memory>
+
 #include <gtest/gtest.h>
 
 #include <android/binder_process.h>
@@ -29,7 +31,7 @@
 class ExtractorTest : public ::testing::TestWithParam<pair<string, int32_t>> {};
 
 TEST_P(ExtractorTest, Extract) {
-    Extractor *extractObj = new Extractor();
+    std::unique_ptr<Extractor> extractObj(new (std::nothrow) Extractor());
     ASSERT_NE(extractObj, nullptr) << "Extractor creation failed";
 
     string inputFile = gEnv->getRes() + GetParam().first;
@@ -53,7 +55,6 @@
     extractObj->dumpStatistics(GetParam().first, "", gEnv->getStatsFile());
 
     fclose(inputFp);
-    delete extractObj;
 }
 
 INSTANTIATE_TEST_SUITE_P(ExtractorTestAll, ExtractorTest,
@@ -76,7 +77,7 @@
 
 int main(int argc, char **argv) {
     ABinderProcess_startThreadPool();
-    gEnv = new BenchmarkTestEnvironment();
+    gEnv = new (std::nothrow) BenchmarkTestEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/tests/benchmark/tests/MuxerTest.cpp b/media/tests/benchmark/tests/MuxerTest.cpp
index 991644b..65a3df4 100644
--- a/media/tests/benchmark/tests/MuxerTest.cpp
+++ b/media/tests/benchmark/tests/MuxerTest.cpp
@@ -20,6 +20,7 @@
 
 #include <fstream>
 #include <iostream>
+#include <memory>
 
 #include "BenchmarkTestEnvironment.h"
 #include "Muxer.h"
@@ -59,7 +60,7 @@
     MUXER_OUTPUT_T outputFormat = getMuxerOutFormat(fmt);
     ASSERT_NE(outputFormat, MUXER_OUTPUT_FORMAT_INVALID) << "Invalid muxer output format";
 
-    Muxer *muxerObj = new Muxer();
+    std::unique_ptr<Muxer> muxerObj(new (std::nothrow) Muxer());
     ASSERT_NE(muxerObj, nullptr) << "Muxer creation failed";
 
     Extractor *extractor = muxerObj->getExtractor();
@@ -78,7 +79,7 @@
         int32_t status = extractor->setupTrackFormat(curTrack);
         ASSERT_EQ(status, 0) << "Track Format invalid";
 
-        uint8_t *inputBuffer = (uint8_t *)malloc(kMaxBufferSize);
+        std::unique_ptr<uint8_t[]> inputBuffer(new (std::nothrow) uint8_t[kMaxBufferSize]);
         ASSERT_NE(inputBuffer, nullptr) << "Insufficient memory";
 
         // AMediaCodecBufferInfo : <size of frame> <flags> <presentationTimeUs> <offset>
@@ -94,7 +95,7 @@
             ASSERT_LE(inputBufferOffset + info.size, kMaxBufferSize)
                     << "Memory allocated not sufficient";
 
-            memcpy(inputBuffer + inputBufferOffset, extractor->getFrameBuf(), info.size);
+            memcpy(inputBuffer.get() + inputBufferOffset, extractor->getFrameBuf(), info.size);
             info.offset = inputBufferOffset;
             frameInfos.push_back(info);
             inputBufferOffset += info.size;
@@ -109,18 +110,16 @@
         status = muxerObj->initMuxer(fd, outputFormat);
         ASSERT_EQ(status, 0) << "initMuxer failed";
 
-        status = muxerObj->mux(inputBuffer, frameInfos);
+        status = muxerObj->mux(inputBuffer.get(), frameInfos);
         ASSERT_EQ(status, 0) << "Mux failed";
 
         muxerObj->deInitMuxer();
         muxerObj->dumpStatistics(GetParam().first + "." + fmt.c_str(), fmt, gEnv->getStatsFile());
-        free(inputBuffer);
         fclose(outputFp);
         muxerObj->resetMuxer();
     }
     fclose(inputFp);
     extractor->deInitExtractor();
-    delete muxerObj;
 }
 
 INSTANTIATE_TEST_SUITE_P(
@@ -146,7 +145,7 @@
                           make_pair("bbb_16000hz_1ch_9kbps_amrwb_5mins.3gp", "3gpp")));
 
 int main(int argc, char **argv) {
-    gEnv = new BenchmarkTestEnvironment();
+    gEnv = new (std::nothrow) BenchmarkTestEnvironment();
     ::testing::AddGlobalTestEnvironment(gEnv);
     ::testing::InitGoogleTest(&argc, argv);
     int status = gEnv->initFromOptions(argc, argv);
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index a38ef57..fddbece 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -69,6 +69,7 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-Wthread-safety",
     ],
 
     header_libs: [
diff --git a/media/utils/MemoryLeakTrackUtil.cpp b/media/utils/MemoryLeakTrackUtil.cpp
index fdb8c4f..7451033 100644
--- a/media/utils/MemoryLeakTrackUtil.cpp
+++ b/media/utils/MemoryLeakTrackUtil.cpp
@@ -33,10 +33,8 @@
 #define ABI_STRING "arm"
 #elif defined(__aarch64__)
 #define ABI_STRING "arm64"
-#elif defined(__mips__) && !defined(__LP64__)
-#define ABI_STRING "mips"
-#elif defined(__mips__) && defined(__LP64__)
-#define ABI_STRING "mips64"
+#elif defined(__riscv)
+#define ABI_STRING "riscv64"
 #elif defined(__i386__)
 #define ABI_STRING "x86"
 #elif defined(__x86_64__)
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index da199c4..8437222 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -40,11 +40,11 @@
     int32_t state;
     int32_t score = INVALID_ADJ;
     status_t err = service->getProcessStatesAndOomScoresFromPids(length, &pid, &state, &score);
+    ALOGV("%s: pid:%d state:%d score:%d err:%d", __FUNCTION__, pid, state, score, err);
     if (err != OK) {
         ALOGE("getProcessStatesAndOomScoresFromPids failed");
         return false;
     }
-    ALOGV("pid %d state %d score %d", pid, state, score);
     if (score <= NATIVE_ADJ) {
         std::scoped_lock lock{mOverrideLock};
 
diff --git a/media/utils/TimeCheck.cpp b/media/utils/TimeCheck.cpp
index 6823f4f..65b2c52 100644
--- a/media/utils/TimeCheck.cpp
+++ b/media/utils/TimeCheck.cpp
@@ -283,7 +283,7 @@
 }
 
 // Automatically create a TimeCheck class for a class and method.
-// This is used for Audio HIDL support.
+// This is used for Audio HAL support.
 mediautils::TimeCheck makeTimeCheckStatsForClassMethod(
         std::string_view className, std::string_view methodName) {
     std::shared_ptr<MethodStatistics<std::string>> statistics =
diff --git a/media/utils/TimerThread.cpp b/media/utils/TimerThread.cpp
index 5e58a3d..d4da28f 100644
--- a/media/utils/TimerThread.cpp
+++ b/media/utils/TimerThread.cpp
@@ -292,6 +292,7 @@
 
 void TimerThread::MonitorThread::threadFunc() {
     std::unique_lock _l(mMutex);
+    ::android::base::ScopedLockAssertion lock_assertion(mMutex);
     while (!mShouldExit) {
         Handle nextDeadline = INVALID_HANDLE;
         Handle now = INVALID_HANDLE;
@@ -385,6 +386,7 @@
 std::shared_ptr<const TimerThread::Request> TimerThread::MonitorThread::remove(Handle handle) {
     std::pair<std::shared_ptr<const Request>, TimerCallback> data;
     std::unique_lock ul(mMutex);
+    ::android::base::ScopedLockAssertion lock_assertion(mMutex);
     if (const auto it = mMonitorRequests.find(handle);
         it != mMonitorRequests.end()) {
         data = std::move(it->second);
diff --git a/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp b/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
index 130feee..32fc3be 100644
--- a/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
+++ b/media/utils/fuzzers/SchedulingPolicyServiceFuzz.cpp
@@ -34,11 +34,16 @@
     const sp<IServiceManager> sm(defaultServiceManager());
     if (sm != nullptr) {
         const String16 name("batterystats");
-        batteryStatService = checked_interface_cast<IBatteryStats>(sm->checkService(name));
-        if (batteryStatService == nullptr) {
+        sp<IBinder> obj = sm->checkService(name);
+        if (!obj) {
             ALOGW("batterystats service unavailable!");
             return nullptr;
         }
+        batteryStatService = checked_interface_cast<IBatteryStats>(obj);
+        if (batteryStatService == nullptr) {
+            ALOGW("batterystats service interface is invalid");
+            return nullptr;
+        }
     }
     return batteryStatService;
 }
diff --git a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
index 51e8d7a..15f043a 100644
--- a/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
+++ b/media/utils/fuzzers/ServiceUtilitiesFuzz.cpp
@@ -25,6 +25,7 @@
 
 static constexpr int kMaxOperations = 50;
 static constexpr int kMaxStringLen = 256;
+static constexpr int kMaxSpaces = 1000;
 
 using android::content::AttributionSourceState;
 
@@ -35,7 +36,9 @@
             pm.allowPlaybackCapture(uid);
         },
         [](FuzzedDataProvider* data_provider, android::MediaPackageManager pm) -> void {
-            int spaces = data_provider->ConsumeIntegral<int>();
+           /* The large value of spaces was taking time in file write operation.
+            * Limited spaces values in range to avoid timeout.*/
+            int spaces = data_provider->ConsumeIntegralInRange<int>(0, kMaxSpaces);
 
             // Dump everything into /dev/null
             int fd = open("/dev/null", O_WRONLY);
diff --git a/media/utils/include/mediautils/TimeCheck.h b/media/utils/include/mediautils/TimeCheck.h
index bdb5337..0823669 100644
--- a/media/utils/include/mediautils/TimeCheck.h
+++ b/media/utils/include/mediautils/TimeCheck.h
@@ -148,4 +148,9 @@
 TimeCheck makeTimeCheckStatsForClassMethod(
         std::string_view className, std::string_view methodName);
 
+// A handy statement-like macro to put at the beginning of almost every method
+// which calls into HAL. Note that it requires the class to implement 'getClassName'.
+#define TIME_CHECK() auto timeCheck = \
+            mediautils::makeTimeCheckStatsForClassMethod(getClassName(), __func__)
+
 }  // namespace android::mediautils
diff --git a/media/utils/include/mediautils/TimerThread.h b/media/utils/include/mediautils/TimerThread.h
index c76fa7d..1e0d8c2 100644
--- a/media/utils/include/mediautils/TimerThread.h
+++ b/media/utils/include/mediautils/TimerThread.h
@@ -297,7 +297,7 @@
                 std::pair<std::shared_ptr<const Request>, TimerCallback>>
                         mSecondChanceRequests GUARDED_BY(mMutex);
 
-        RequestQueue& mTimeoutQueue; // locked internally, added to when request times out.
+        RequestQueue& mTimeoutQueue GUARDED_BY(mMutex); // added to when request times out.
 
         // Worker thread variables
         bool mShouldExit GUARDED_BY(mMutex) = false;
diff --git a/services/OWNERS b/services/OWNERS
deleted file mode 100644
index 17e605d..0000000
--- a/services/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-elaurent@google.com
-essick@google.com
-etalvala@google.com
-hunga@google.com
-nchalko@google.com
-quxiangfang@google.com
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 763c070..6d4c3a3 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -22,6 +22,10 @@
 cc_library_shared {
     name: "libaudioflinger",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     srcs: [
         "AudioFlinger.cpp",
         "AudioHwDevice.cpp",
@@ -55,7 +59,6 @@
     ],
 
     shared_libs: [
-        "android.media.audio.common.types-V1-cpp",
         "audioflinger-aidl-cpp",
         "audioclient-types-aidl-cpp",
         "av-types-aidl-cpp",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d2363d8..ba7c6b6 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -39,6 +39,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include <binder/Parcel.h>
+#include <media/audiohal/AudioHalVersionInfo.h>
 #include <media/audiohal/DeviceHalInterface.h>
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -106,13 +107,15 @@
 
 namespace android {
 
-#define MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION 7.1
-
 using ::android::base::StringPrintf;
 using media::IEffectClient;
 using media::audio::common::AudioMMapPolicyInfo;
 using media::audio::common::AudioMMapPolicyType;
 using android::content::AttributionSourceState;
+using android::detail::AudioHalVersionInfo;
+
+static const AudioHalVersionInfo kMaxAAudioPropertyDeviceHalVersion =
+        AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 7, 1);
 
 static const char kDeadlockedString[] = "AudioFlinger may be deadlocked\n";
 static const char kHardwareLockedString[] = "Hardware lock is taken\n";
@@ -228,7 +231,9 @@
 BINDER_METHOD_ENTRY(setDeviceConnectedState) \
 BINDER_METHOD_ENTRY(setRequestedLatencyMode) \
 BINDER_METHOD_ENTRY(getSupportedLatencyModes) \
-
+BINDER_METHOD_ENTRY(setBluetoothVariableLatencyEnabled) \
+BINDER_METHOD_ENTRY(isBluetoothVariableLatencyEnabled) \
+BINDER_METHOD_ENTRY(supportsBluetoothVariableLatency) \
 
 // singleton for Binder Method Statistics for IAudioFlinger
 static auto& getIAudioFlingerStatistics() {
@@ -322,7 +327,8 @@
       mGlobalEffectEnableTime(0),
       mPatchPanel(this),
       mDeviceEffectManager(this),
-      mSystemReady(false)
+      mSystemReady(false),
+      mBluetoothLatencyModesEnabled(true)
 {
     // Move the audio session unique ID generator start base as time passes to limit risk of
     // generating the same ID again after an audioserver restart.
@@ -398,7 +404,7 @@
     mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
     mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
 
-    if (mDevicesFactoryHal->getHalVersion() <= MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+    if (mDevicesFactoryHal->getHalVersion() <= kMaxAAudioPropertyDeviceHalVersion) {
         mAAudioBurstsPerBuffer = getAAudioMixerBurstCountFromSystemProperty();
         mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
     }
@@ -444,7 +450,7 @@
         *policyInfos = it->second;
         return NO_ERROR;
     }
-    if (mDevicesFactoryHal->getHalVersion() > MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+    if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
         AutoMutex lock(mHardwareLock);
         for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
             AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
@@ -1640,6 +1646,44 @@
     return thread->getSupportedLatencyModes(modes);
 }
 
+status_t AudioFlinger::setBluetoothVariableLatencyEnabled(bool enabled) {
+    Mutex::Autolock _l(mLock);
+    status_t status = INVALID_OPERATION;
+    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
+        // Success if at least one PlaybackThread supports Bluetooth latency modes
+        if (mPlaybackThreads.valueAt(i)->setBluetoothVariableLatencyEnabled(enabled) == NO_ERROR) {
+            status = NO_ERROR;
+        }
+    }
+    if (status == NO_ERROR) {
+        mBluetoothLatencyModesEnabled.store(enabled);
+    }
+    return status;
+}
+
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+    if (enabled == nullptr) {
+        return BAD_VALUE;
+    }
+    *enabled = mBluetoothLatencyModesEnabled.load();
+    return NO_ERROR;
+}
+
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
+    if (support == nullptr) {
+        return BAD_VALUE;
+    }
+    Mutex::Autolock _l(mLock);
+    *support = false;
+    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
+        if (mAudioHwDevs.valueAt(i)->supportsBluetoothVariableLatency()) {
+             *support = true;
+             break;
+        }
+    }
+    return NO_ERROR;
+}
+
 status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
 {
     // check calling permissions
@@ -2142,9 +2186,9 @@
 void AudioFlinger::onSupportedLatencyModesChanged(
         audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) {
     int32_t outputAidl = VALUE_OR_FATAL(legacy2aidl_audio_io_handle_t_int32_t(output));
-    std::vector<media::LatencyMode> modesAidl = VALUE_OR_FATAL(
-                convertContainer<std::vector<media::LatencyMode>>(modes,
-                        legacy2aidl_audio_latency_mode_t_LatencyMode));
+    std::vector<media::audio::common::AudioLatencyMode> modesAidl = VALUE_OR_FATAL(
+                convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
+                        modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
 
     Mutex::Autolock _l(mClientLock);
     size_t size = mNotificationClients.size();
@@ -2541,6 +2585,13 @@
         flags = static_cast<AudioHwDevice::Flags>(flags | AudioHwDevice::AHWD_IS_INSERT);
     }
 
+
+    if (bool supports = false;
+            dev->supportsBluetoothVariableLatency(&supports) == NO_ERROR && supports) {
+        flags = static_cast<AudioHwDevice::Flags>(flags |
+                AudioHwDevice::AHWD_SUPPORTS_BT_LATENCY_MODES);
+    }
+
     audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
     AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
     if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
@@ -2550,7 +2601,7 @@
         mHardwareStatus = AUDIO_HW_IDLE;
     }
 
-    if (mDevicesFactoryHal->getHalVersion() > MAX_AAUDIO_PROPERTY_DEVICE_HAL_VERSION) {
+    if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
         if (int32_t mixerBursts = dev->getAAudioMixerBurstCount();
             mixerBursts > 0 && mixerBursts > mAAudioBurstsPerBuffer) {
             mAAudioBurstsPerBuffer = mixerBursts;
@@ -2748,20 +2799,25 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfo> *microphones)
+status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones)
 {
     AutoMutex lock(mHardwareLock);
     status_t status = INVALID_OPERATION;
 
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-        std::vector<media::MicrophoneInfo> mics;
+        std::vector<audio_microphone_characteristic_t> mics;
         AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
         mHardwareStatus = AUDIO_HW_GET_MICROPHONES;
         status_t devStatus = dev->hwDevice()->getMicrophones(&mics);
         mHardwareStatus = AUDIO_HW_IDLE;
         if (devStatus == NO_ERROR) {
-            microphones->insert(microphones->begin(), mics.begin(), mics.end());
             // report success if at least one HW module supports the function.
+            std::transform(mics.begin(), mics.end(), std::back_inserter(*microphones), [](auto& mic)
+            {
+                auto microphone =
+                        legacy2aidl_audio_microphone_characteristic_t_MicrophoneInfoFw(mic);
+                return microphone.ok() ? microphone.value() : media::MicrophoneInfoFw{};
+            });
             status = NO_ERROR;
         }
     }
@@ -2869,13 +2925,15 @@
                 ALOGV("openOutput_l() created spatializer output: ID %d thread %p",
                       *output, thread.get());
             } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-                thread = new OffloadThread(this, outputStream, *output, mSystemReady);
+                thread = new OffloadThread(this, outputStream, *output,
+                        mSystemReady, halConfig->offload_info);
                 ALOGV("openOutput_l() created offload output: ID %d thread %p",
                       *output, thread.get());
             } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                     || !isValidPcmSinkFormat(halConfig->format)
                     || !isValidPcmSinkChannelMask(halConfig->channel_mask)) {
-                thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
+                thread = new DirectOutputThread(this, outputStream, *output,
+                        mSystemReady, halConfig->offload_info);
                 ALOGV("openOutput_l() created direct output: ID %d thread %p",
                       *output, thread.get());
             } else {
@@ -2889,6 +2947,7 @@
             if (thread->isMsdDevice()) {
                 thread->setDownStreamPatch(&patch);
             }
+            thread->setBluetoothVariableLatencyEnabled(mBluetoothLatencyModesEnabled.load());
             return thread;
         }
     }
@@ -4526,12 +4585,9 @@
 // ----------------------------------------------------------------------------
 
 status_t AudioFlinger::onTransactWrapper(TransactionCode code,
-                                         const Parcel& data,
-                                         uint32_t flags,
+                                         [[maybe_unused]] const Parcel& data,
+                                         [[maybe_unused]] uint32_t flags,
                                          const std::function<status_t()>& delegate) {
-    (void) data;
-    (void) flags;
-
     // make sure transactions reserved to AudioPolicyManager do not come from other processes
     switch (code) {
         case TransactionCode::SET_STREAM_VOLUME:
@@ -4585,7 +4641,10 @@
         case TransactionCode::SYSTEM_READY:
         case TransactionCode::SET_AUDIO_HAL_PIDS:
         case TransactionCode::SET_VIBRATOR_INFOS:
-        case TransactionCode::UPDATE_SECONDARY_OUTPUTS: {
+        case TransactionCode::UPDATE_SECONDARY_OUTPUTS:
+        case TransactionCode::SET_BLUETOOTH_VARIABLE_LATENCY_ENABLED:
+        case TransactionCode::IS_BLUETOOTH_VARIABLE_LATENCY_ENABLED:
+        case TransactionCode::SUPPORTS_BLUETOOTH_VARIABLE_LATENCY: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index fc4c807..ebfe32c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -274,7 +274,7 @@
             bool isAudioPolicyReady() const { return mAudioPolicyReady.load(); }
 
 
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfo> *microphones);
+    virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
 
     virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
 
@@ -299,6 +299,12 @@
     virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
             std::vector<audio_latency_mode_t>* modes);
 
+    virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+
+    virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+
+    virtual status_t supportsBluetoothVariableLatency(bool* support);
+
     status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
         const std::function<status_t()>& delegate) override;
 
@@ -678,14 +684,16 @@
         binder::Status getVolumeShaperState(
                 int32_t id,
                 std::optional<media::VolumeShaperState>* _aidl_return) override;
-        binder::Status getDualMonoMode(media::AudioDualMonoMode* _aidl_return) override;
-        binder::Status setDualMonoMode(media::AudioDualMonoMode mode) override;
+        binder::Status getDualMonoMode(
+                media::audio::common::AudioDualMonoMode* _aidl_return) override;
+        binder::Status setDualMonoMode(
+                media::audio::common::AudioDualMonoMode mode) override;
         binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
         binder::Status setAudioDescriptionMixLevel(float leveldB) override;
         binder::Status getPlaybackRateParameters(
-                media::AudioPlaybackRate* _aidl_return) override;
+                media::audio::common::AudioPlaybackRate* _aidl_return) override;
         binder::Status setPlaybackRateParameters(
-                const media::AudioPlaybackRate& playbackRate) override;
+                const media::audio::common::AudioPlaybackRate& playbackRate) override;
 
     private:
         const sp<PlaybackThread::Track> mTrack;
@@ -700,7 +708,7 @@
                 int /*audio_session_t*/ triggerSession);
         virtual binder::Status   stop();
         virtual binder::Status   getActiveMicrophones(
-                std::vector<media::MicrophoneInfoData>* activeMicrophones);
+                std::vector<media::MicrophoneInfoFw>* activeMicrophones);
         virtual binder::Status   setPreferredMicrophoneDirection(
                 int /*audio_microphone_direction_t*/ direction);
         virtual binder::Status   setPreferredMicrophoneFieldDimension(float zoom);
@@ -1029,6 +1037,9 @@
              std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos;
     int32_t mAAudioBurstsPerBuffer = 0;
     int32_t mAAudioHwBurstMinMicros = 0;
+
+    // Bluetooth Variable latency control logic is enabled or disabled
+    std::atomic_bool mBluetoothLatencyModesEnabled;
 };
 
 #undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audioflinger/AudioHwDevice.h b/services/audioflinger/AudioHwDevice.h
index 8c5d239..1749f3f 100644
--- a/services/audioflinger/AudioHwDevice.h
+++ b/services/audioflinger/AudioHwDevice.h
@@ -40,6 +40,8 @@
         // Means that this isn't a terminal module, and software patches
         // are used to transport audio data further.
         AHWD_IS_INSERT              = 0x4,
+        // This Module supports BT Latency mode control
+        AHWD_SUPPORTS_BT_LATENCY_MODES = 0x8,
     };
 
     AudioHwDevice(audio_module_handle_t handle,
@@ -64,6 +66,10 @@
         return (0 != (mFlags & AHWD_IS_INSERT));
     }
 
+    bool supportsBluetoothVariableLatency() const {
+        return (0 != (mFlags & AHWD_SUPPORTS_BT_LATENCY_MODES));
+    }
+
     audio_module_handle_t handle() const { return mHandle; }
     const char *moduleName() const { return mModuleName; }
     sp<DeviceHalInterface> hwDevice() const { return mHwDevice; }
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 53ac5cb..3a8c1bc 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -30,6 +30,7 @@
 
 namespace android {
 
+using detail::AudioHalVersionInfo;
 using media::IEffectClient;
 
 void AudioFlinger::DeviceEffectManager::createAudioPatch(audio_patch_handle_t handle,
@@ -106,8 +107,13 @@
         if (lStatus == NO_ERROR) {
             lStatus = effect->addHandle(handle.get());
             if (lStatus == NO_ERROR) {
-                effect->init(patches);
-                mDeviceEffects.emplace(device, effect);
+                lStatus = effect->init(patches);
+                if (lStatus == NAME_NOT_FOUND) {
+                    lStatus = NO_ERROR;
+                }
+                if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
+                    mDeviceEffects.emplace(device, effect);
+                }
             }
         }
     }
@@ -125,14 +131,17 @@
         return BAD_VALUE;
     }
 
-    static const float sMinDeviceEffectHalVersion = 6.0;
-    float halVersion = effectsFactory->getHalVersion();
+    static AudioHalVersionInfo sMinDeviceEffectHalVersion =
+            AudioHalVersionInfo(AudioHalVersionInfo::Type::HIDL, 6, 0);
+    AudioHalVersionInfo halVersion = effectsFactory->getHalVersion();
 
+    // We can trust AIDL generated AudioHalVersionInfo comparison operator (based on std::tie) as
+    // long as the type, major and minor sequence doesn't change in the definition.
     if (((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC
             && (desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC)
             || halVersion < sMinDeviceEffectHalVersion) {
-        ALOGW("%s() non pre/post processing device effect %s or incompatible API version %f",
-                __func__, desc->name, halVersion);
+        ALOGW("%s() non pre/post processing device effect %s or incompatible API version %s",
+                __func__, desc->name, halVersion.toString().c_str());
         return BAD_VALUE;
     }
 
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 9ebff0b..98829d0 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -569,7 +569,8 @@
       mMaxDisableWaitCnt(1), // set by configure(), should be >= 1
       mDisableWaitCnt(0),    // set by process() and updateState()
       mOffloaded(false),
-      mAddedToHal(false)
+      mAddedToHal(false),
+      mIsOutput(false)
 #ifdef FLOAT_EFFECT_CHAIN
       , mSupportsFloat(false)
 #endif
@@ -962,6 +963,7 @@
     mConfig.outputCfg.mask = EFFECT_CONFIG_ALL;
     mConfig.inputCfg.buffer.frameCount = callback->frameCount();
     mConfig.outputCfg.buffer.frameCount = mConfig.inputCfg.buffer.frameCount;
+    mIsOutput = callback->isOutput();
 
     ALOGV("configure() %p chain %p buffer %p framecount %zu",
           this, callback->chain().promote().get(),
@@ -980,7 +982,7 @@
 
 #ifdef MULTICHANNEL_EFFECT_CHAIN
     if (status != NO_ERROR &&
-            callback->isOutput() &&
+            mIsOutput &&
             (mConfig.inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO
                     || mConfig.outputCfg.channels != AUDIO_CHANNEL_OUT_STEREO)) {
         // Older effects may require exact STEREO position mask.
@@ -1056,6 +1058,13 @@
                     &size,
                     &cmdStatus);
         }
+
+        if (isVolumeControl()) {
+            // Force initializing the volume as 0 for volume control effect for safer ramping
+            uint32_t left = 0;
+            uint32_t right = 0;
+            setVolumeInternal(&left, &right, true /*controller*/);
+        }
     }
 
     // mConfig.outputCfg.buffer.frameCount cannot be zero.
@@ -1429,23 +1438,24 @@
             ((mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL ||
              (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_IND ||
              (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_MONITOR)) {
-        uint32_t volume[2];
-        uint32_t *pVolume = NULL;
-        uint32_t size = sizeof(volume);
-        volume[0] = *left;
-        volume[1] = *right;
-        if (controller) {
-            pVolume = volume;
-        }
-        status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
-                                           size,
-                                           volume,
-                                           &size,
-                                           pVolume);
-        if (controller && status == NO_ERROR && size == sizeof(volume)) {
-            *left = volume[0];
-            *right = volume[1];
-        }
+        status = setVolumeInternal(left, right, controller);
+    }
+    return status;
+}
+
+status_t AudioFlinger::EffectModule::setVolumeInternal(
+        uint32_t *left, uint32_t *right, bool controller) {
+    uint32_t volume[2] = {*left, *right};
+    uint32_t *pVolume = controller ? volume : nullptr;
+    uint32_t size = sizeof(volume);
+    status_t status = mEffectInterface->command(EFFECT_CMD_SET_VOLUME,
+                                                size,
+                                                volume,
+                                                &size,
+                                                pVolume);
+    if (controller && status == NO_ERROR && size == sizeof(volume)) {
+        *left = volume[0];
+        *right = volume[1];
     }
     return status;
 }
@@ -1643,6 +1653,22 @@
     return status;
 }
 
+status_t AudioFlinger::EffectModule::getConfigs(
+        audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
+    Mutex::Autolock _l(mLock);
+    if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
+        return NO_INIT;
+    }
+    inputCfg->sample_rate = mConfig.inputCfg.samplingRate;
+    inputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.inputCfg.channels);
+    inputCfg->format = static_cast<audio_format_t>(mConfig.inputCfg.format);
+    outputCfg->sample_rate = mConfig.outputCfg.samplingRate;
+    outputCfg->channel_mask = static_cast<audio_channel_mask_t>(mConfig.outputCfg.channels);
+    outputCfg->format = static_cast<audio_format_t>(mConfig.outputCfg.format);
+    *isOutput = mIsOutput;
+    return NO_ERROR;
+}
+
 static std::string dumpInOutBuffer(bool isInput, const sp<EffectBufferHalInterface> &buffer) {
     std::stringstream ss;
 
@@ -1761,6 +1787,7 @@
 BINDER_METHOD_ENTRY(command) \
 BINDER_METHOD_ENTRY(disconnect) \
 BINDER_METHOD_ENTRY(getCblk) \
+BINDER_METHOD_ENTRY(getConfig) \
 
 // singleton for Binder Method Statistics for IEffect
 mediautils::MethodStatistics<int>& getIEffectStatistics() {
@@ -1804,6 +1831,13 @@
   *_aidl_return = (code); \
   return Status::ok();
 
+#define VALUE_OR_RETURN_STATUS_AS_OUT(exp)              \
+    ({                                                  \
+        auto _tmp = (exp);                              \
+        if (!_tmp.ok()) { RETURN(_tmp.error()); }       \
+        std::move(_tmp.value());                        \
+    })
+
 Status AudioFlinger::EffectHandle::enable(int32_t* _aidl_return)
 {
     AutoMutex _l(mLock);
@@ -1915,6 +1949,32 @@
     return Status::ok();
 }
 
+Status AudioFlinger::EffectHandle::getConfig(
+        media::EffectConfig* _config, int32_t* _aidl_return) {
+    AutoMutex _l(mLock);
+    sp<EffectBase> effect = mEffect.promote();
+    if (effect == nullptr || mDisconnected) {
+        RETURN(DEAD_OBJECT);
+    }
+    sp<EffectModule> effectModule = effect->asEffectModule();
+    if (effectModule == nullptr) {
+        RETURN(INVALID_OPERATION);
+    }
+    audio_config_base_t inputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
+    audio_config_base_t outputCfg = AUDIO_CONFIG_BASE_INITIALIZER;
+    bool isOutput;
+    status_t status = effectModule->getConfigs(&inputCfg, &outputCfg, &isOutput);
+    if (status == NO_ERROR) {
+        constexpr bool isInput = false; // effects always use 'OUT' channel masks.
+        _config->inputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
+                legacy2aidl_audio_config_base_t_AudioConfigBase(inputCfg, isInput));
+        _config->outputCfg = VALUE_OR_RETURN_STATUS_AS_OUT(
+                legacy2aidl_audio_config_base_t_AudioConfigBase(outputCfg, isInput));
+        _config->isOnInputStream = !isOutput;
+    }
+    RETURN(status);
+}
+
 Status AudioFlinger::EffectHandle::command(int32_t cmdCode,
                        const std::vector<uint8_t>& cmdData,
                        int32_t maxResponseSize,
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 42614cc..78788df 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -283,6 +283,10 @@
     status_t         setHapticIntensity(int id, int intensity);
     status_t         setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo);
 
+    status_t         getConfigs(audio_config_base_t* inputCfg,
+                                audio_config_base_t* outputCfg,
+                                bool* isOutput) const;
+
     void             dump(int fd, const Vector<String16>& args);
 
 private:
@@ -302,6 +306,8 @@
                 ? EFFECT_BUFFER_ACCESS_WRITE : EFFECT_BUFFER_ACCESS_ACCUMULATE;
     }
 
+    status_t setVolumeInternal(uint32_t *left, uint32_t *right, bool controller);
+
 
     effect_config_t     mConfig;    // input and output audio configuration
     sp<EffectHalInterface> mEffectInterface; // Effect module HAL
@@ -314,6 +320,7 @@
     uint32_t mDisableWaitCnt;       // current process() calls count during disable period.
     bool     mOffloaded;            // effect is currently offloaded to the audio DSP
     bool     mAddedToHal;           // effect has been added to the audio HAL
+    bool     mIsOutput;             // direction of the AF thread
 
 #ifdef FLOAT_EFFECT_CHAIN
     bool    mSupportsFloat;         // effect supports float processing
@@ -370,6 +377,8 @@
                                     int32_t* _aidl_return) override;
     android::binder::Status disconnect() override;
     android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
+    android::binder::Status getConfig(media::EffectConfig* _config,
+                                      int32_t* _aidl_return) override;
 
     sp<Client> client() const { return mClient; }
 
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 26bd92d..61dd3f2 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -79,8 +79,6 @@
     mMasterMono(false),
     mThreadIoHandle(parentIoHandle)
 {
-    (void)mThreadIoHandle; // prevent unused warning, see C++17 [[maybe_unused]]
-
     // FIXME pass sInitial as parameter to base class constructor, and make it static local
     mPrevious = &sInitial;
     mCurrent = &sInitial;
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index 97ab635..d71519f 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -107,7 +107,8 @@
     std::atomic<float> mMasterBalance{};
     std::atomic_int_fast64_t mBoottimeOffset;
 
-    const audio_io_handle_t mThreadIoHandle; // parent thread id for debugging purposes
+    // parent thread id for debugging purposes
+    [[maybe_unused]] const audio_io_handle_t mThreadIoHandle;
 #ifdef TEE_SINK
     NBAIO_Tee       mTee;
 #endif
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 93593a3..68a3800 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -31,7 +31,6 @@
                   mPlaybackThreadHandle(playbackThreadHandle),
                   mRecordThreadHandle(recordThreadHandle) {}
         SoftwarePatch(const SoftwarePatch&) = default;
-        SoftwarePatch& operator=(const SoftwarePatch&) = default;
 
         // Must be called under AudioFlinger::mLock
         status_t getLatencyMs_l(double *latencyMs) const;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 6a138bb..33983d7 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -310,6 +310,7 @@
         binder::Status unmute(/*out*/ bool *ret) override;
     private:
         Track* const mTrack;
+        bool setMute(bool muted);
     };
     sp<AudioVibrationController> mAudioVibrationController;
     sp<os::ExternalVibration>    mExternalVibration;
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index daec57e..f0a5f76 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -73,7 +73,8 @@
             void        setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
             bool        isSilenced() const { return mSilenced; }
 
-            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+            status_t    getActiveMicrophones(
+                    std::vector<media::MicrophoneInfoFw>* activeMicrophones);
 
             status_t    setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
             status_t    setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 73ee691..37b8fe8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -271,8 +271,8 @@
 
 static std::string toString(audio_latency_mode_t mode) {
     // We convert to the AIDL type to print (eventually the legacy type will be removed).
-    const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
-    return result.has_value() ? media::toString(*result) : "UNKNOWN";
+    const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+    return result.has_value() ? media::audio::common::toString(*result) : "UNKNOWN";
 }
 
 // Could be made a template, but other toString overloads for std::vector are confused.
@@ -2063,7 +2063,8 @@
         mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
         mLeftVolFloat(-1.0), mRightVolFloat(-1.0),
         mDownStreamPatch{},
-        mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs)
+        mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs),
+        mBluetoothLatencyModesEnabled(true)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
     mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -2139,9 +2140,19 @@
     if (!isStreamInitialized()) {
         ALOGE("The stream is not open yet"); // This should not happen.
     } else {
-        // setEventCallback will need a strong pointer as a parameter. Calling it
-        // here instead of constructor of PlaybackThread so that the onFirstRef
-        // callback would not be made on an incompletely constructed object.
+        // Callbacks take strong or weak pointers as a parameter.
+        // Since PlaybackThread passes itself as a callback handler, it can only
+        // be done outside of the constructor. Creating weak and especially strong
+        // pointers to a refcounted object in its own constructor is strongly
+        // discouraged, see comments in system/core/libutils/include/utils/RefBase.h.
+        // Even if a function takes a weak pointer, it is possible that it will
+        // need to convert it to a strong pointer down the line.
+        if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING &&
+                mOutput->stream->setCallback(this) == OK) {
+            mUseAsyncWrite = true;
+            mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
+        }
+
         if (mOutput->stream->setEventCallback(this) != OK) {
             ALOGD("Failed to add event callback");
         }
@@ -2908,7 +2919,14 @@
 void AudioFlinger::PlaybackThread::onCodecFormatChanged(
         const std::basic_string<uint8_t>& metadataBs)
 {
-    std::thread([this, metadataBs]() {
+    wp<AudioFlinger::PlaybackThread> weakPointerThis = this;
+    std::thread([this, metadataBs, weakPointerThis]() {
+            sp<AudioFlinger::PlaybackThread> playbackThread = weakPointerThis.promote();
+            if (playbackThread == nullptr) {
+                ALOGW("PlaybackThread was destroyed, skip codec format change event");
+                return;
+            }
+
             audio_utils::metadata::Data metadata =
                     audio_utils::metadata::dataFromByteString(metadataBs);
             if (metadata.empty()) {
@@ -2999,13 +3017,6 @@
                 mFrameCount);
     }
 
-    if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING) {
-        if (mOutput->stream->setCallback(this) == OK) {
-            mUseAsyncWrite = true;
-            mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
-        }
-    }
-
     mHwSupportsPause = false;
     if (mOutput->flags & AUDIO_OUTPUT_FLAG_DIRECT) {
         bool supportsPause = false, supportsResume = false;
@@ -3282,7 +3293,7 @@
 }
 
 void AudioFlinger::PlaybackThread::threadLoop_removeTracks(
-        const Vector< sp<Track> >& tracksToRemove)
+        [[maybe_unused]] const Vector< sp<Track> >& tracksToRemove)
 {
     // Miscellaneous track cleanup when removed from the active list,
     // called without Thread lock but synchronized with threadLoop processing.
@@ -3293,8 +3304,6 @@
             addBatteryData(IMediaPlayerService::kBatteryDataAudioFlingerStop);
         }
     }
-#else
-    (void)tracksToRemove; // suppress unused warning
 #endif
 }
 
@@ -3527,9 +3536,9 @@
             if (result != OK) return result;
 
 #ifdef FLOAT_EFFECT_CHAIN
-            buffer = halInBuffer->audioBuffer()->f32;
+            buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
 #else
-            buffer = halInBuffer->audioBuffer()->s16;
+            buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
 #endif
             ALOGV("addEffectChain_l() creating new input buffer %p session %d",
                     buffer, session);
@@ -3558,7 +3567,8 @@
         halOutBuffer = halInBuffer;
         ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
         if (!audio_is_global_session(session)) {
-            buffer = reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData());
+            buffer = halInBuffer ? reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData())
+                                 : buffer;
             // Only one effect chain can be present in direct output thread and it uses
             // the sink buffer as input
             if (mType != DIRECT) {
@@ -3570,9 +3580,9 @@
                         &halInBuffer);
                 if (result != OK) return result;
 #ifdef FLOAT_EFFECT_CHAIN
-                buffer = halInBuffer->audioBuffer()->f32;
+                buffer = halInBuffer ? halInBuffer->audioBuffer()->f32 : buffer;
 #else
-                buffer = halInBuffer->audioBuffer()->s16;
+                buffer = halInBuffer ? halInBuffer->audioBuffer()->s16 : buffer;
 #endif
                 ALOGV("addEffectChain_l() creating new input buffer %p session %d",
                         buffer, session);
@@ -5817,7 +5827,7 @@
     }
 
     // Push the new FastMixer state if necessary
-    bool pauseAudioWatchdog = false;
+    [[maybe_unused]] bool pauseAudioWatchdog = false;
     if (didModify) {
         state->mFastTracksGen++;
         // if the fast mixer was active, but now there are no fast tracks, then put it in cold idle
@@ -6133,8 +6143,10 @@
 // ----------------------------------------------------------------------------
 
 AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady)
+        AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
+        const audio_offload_info_t& offloadInfo)
     :   PlaybackThread(audioFlinger, output, id, type, systemReady)
+    , mOffloadInfo(offloadInfo)
 {
     setMasterBalance(audioFlinger->getMasterBalance_l());
 }
@@ -6400,7 +6412,8 @@
                 // fill a buffer, then remove it from active list.
                 // Only consider last track started for mixer state control
                 bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
-                if (--(track->mRetryCount) <= 0) {
+                if (!isTunerStream()  // tuner streams remain active in underrun
+                        && --(track->mRetryCount) <= 0) {
                     if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
                         track->mRetryCount = kMaxTrackRetriesOffload;
                     } else {
@@ -6444,6 +6457,7 @@
             (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
         status_t result = mOutput->stream->pause();
         ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
+        doHwResume = !doHwPause;  // resume if pause is due to flush.
     }
     if (mFlushPending) {
         flushHw_l();
@@ -6763,8 +6777,9 @@
 
 // ----------------------------------------------------------------------------
 AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
-        AudioStreamOut* output, audio_io_handle_t id, bool systemReady)
-    :   DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady),
+        AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
+        const audio_offload_info_t& offloadInfo)
+    :   DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady, offloadInfo),
         mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
 {
     //FIXME: mStandby should be set to true by ThreadBase constructo
@@ -6983,7 +6998,8 @@
                 // No buffers for this track. Give it a few chances to
                 // fill a buffer, then remove it from active list.
                 bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
-                if (--(track->mRetryCount) <= 0) {
+                if (!isTunerStream()  // tuner streams remain active in underrun
+                        && --(track->mRetryCount) <= 0) {
                     if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
                         track->mRetryCount = kMaxTrackRetriesOffload;
                     } else {
@@ -7012,6 +7028,7 @@
     if (!mStandby && (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
         status_t result = mOutput->stream->pause();
         ALOGE_IF(result != OK, "Error when pausing output stream: %d", result);
+        doHwResume = !doHwPause;  // resume if pause is due to flush.
     }
     if (mFlushPending) {
         flushHw_l();
@@ -7427,6 +7444,15 @@
     return NO_ERROR;
 }
 
+status_t AudioFlinger::PlaybackThread::setBluetoothVariableLatencyEnabled(bool enabled) {
+    if (mOutput == nullptr || mOutput->audioHwDev == nullptr
+            || !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
+        return INVALID_OPERATION;
+    }
+    mBluetoothLatencyModesEnabled.store(enabled);
+    return NO_ERROR;
+}
+
 void AudioFlinger::SpatializerThread::checkOutputStageEffects()
 {
     bool hasVirtualizer = false;
@@ -7542,7 +7568,7 @@
     size_t numCounterOffers = 0;
     const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount, mFormat)};
 #if !LOG_NDEBUG
-    ssize_t index =
+    [[maybe_unused]] ssize_t index =
 #else
     (void)
 #endif
@@ -7561,10 +7587,11 @@
         ALOGV("%p kUseFastCapture = Always, initFastCapture = true", this);
         break;
     case FastCapture_Static:
-        initFastCapture = (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
-        ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d",
-                this, (long long)mFrameCount, mSampleRate, kMinNormalCaptureBufferSizeMs,
-                initFastCapture);
+        initFastCapture = !mIsMsdDevice // Disable fast capture for MSD BUS devices.
+                && (mFrameCount * 1000) / mSampleRate < kMinNormalCaptureBufferSizeMs;
+        ALOGV("%p kUseFastCapture = Static, (%lld * 1000) / %u vs %u, initFastCapture = %d "
+                "mIsMsdDevice = %d", this, (long long)mFrameCount, mSampleRate,
+                kMinNormalCaptureBufferSizeMs, initFastCapture, mIsMsdDevice);
         break;
     // case FastCapture_Dynamic:
     }
@@ -7592,7 +7619,7 @@
         Pipe *pipe = new Pipe(pipeFramesP2, format, pipeBuffer);
         const NBAIO_Format offers[1] = {format};
         size_t numCounterOffers = 0;
-        ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
+        [[maybe_unused]] ssize_t index = pipe->negotiate(offers, 1, NULL, numCounterOffers);
         ALOG_ASSERT(index == 0);
         mPipeSink = pipe;
         PipeReader *pipeReader = new PipeReader(*pipe);
@@ -8696,7 +8723,7 @@
 }
 
 status_t AudioFlinger::RecordThread::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo>* activeMicrophones)
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones)
 {
     ALOGV("RecordThread::getActiveMicrophones");
     AutoMutex _l(mLock);
@@ -9048,7 +9075,8 @@
     audio_format_t reqFormat = mFormat;
     uint32_t samplingRate = mSampleRate;
     // TODO this may change if we want to support capture from HDMI PCM multi channel (e.g on TVs).
-    audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(mChannelCount);
+    [[maybe_unused]] audio_channel_mask_t channelMask =
+                                audio_channel_in_mask_from_count(mChannelCount);
 
     AudioParameter param = AudioParameter(keyValuePair);
     int value;
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index ad5617d..ce90767 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1086,6 +1086,8 @@
                     return INVALID_OPERATION;
                 }
 
+    virtual     status_t setBluetoothVariableLatencyEnabled(bool enabled);
+
 protected:
     // updated by readOutputParameters_l()
     size_t                          mNormalFrameCount;  // normal mixer and effects
@@ -1436,6 +1438,9 @@
     virtual     void flushHw_l() {
                     mIsTimestampAdvancing.clear();
                 }
+
+        // Bluetooth Variable latency control logic is enabled or disabled for this thread
+        std::atomic_bool mBluetoothLatencyModesEnabled;
 };
 
 class MixerThread : public PlaybackThread {
@@ -1541,8 +1546,9 @@
 public:
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                       audio_io_handle_t id, bool systemReady)
-        : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady) { }
+                       audio_io_handle_t id, bool systemReady,
+                       const audio_offload_info_t& offloadInfo)
+        : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady, offloadInfo) { }
 
     virtual                 ~DirectOutputThread();
 
@@ -1574,11 +1580,14 @@
 
     virtual     void        onAddNewTrack_l();
 
+    const       audio_offload_info_t mOffloadInfo;
     bool mVolumeShaperActive = false;
 
     DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                       audio_io_handle_t id, ThreadBase::type_t type, bool systemReady);
+                       audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
+                       const audio_offload_info_t& offloadInfo);
     void processVolume_l(Track *track, bool lastTrack);
+    bool isTunerStream() const { return (mOffloadInfo.content_id > 0); }
 
     // prepareTracks_l() tells threadLoop_mix() the name of the single active track
     sp<Track>               mActiveTrack;
@@ -1616,7 +1625,8 @@
 public:
 
     OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
-                  audio_io_handle_t id, bool systemReady);
+                  audio_io_handle_t id, bool systemReady,
+                  const audio_offload_info_t& offloadInfo);
     virtual                 ~OffloadThread() {};
                 void        flushHw_l() override;
 
@@ -1931,7 +1941,8 @@
             // Sets the UID records silence
             void        setRecordSilenced(audio_port_handle_t portId, bool silenced);
 
-            status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+            status_t    getActiveMicrophones(
+                    std::vector<media::MicrophoneInfoFw>* activeMicrophones);
 
             status_t    setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
             status_t    setPreferredMicrophoneFieldDimension(float zoom);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 10f9f73..300ad9f 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -439,7 +439,8 @@
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::getDualMonoMode(media::AudioDualMonoMode* _aidl_return)
+Status AudioFlinger::TrackHandle::getDualMonoMode(
+        media::audio::common::AudioDualMonoMode* _aidl_return)
 {
     audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
     const status_t status = mTrack->getDualMonoMode(&mode)
@@ -452,7 +453,7 @@
 }
 
 Status AudioFlinger::TrackHandle::setDualMonoMode(
-        media::AudioDualMonoMode mode)
+        media::audio::common::AudioDualMonoMode mode)
 {
     const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioDualMonoMode_audio_dual_mono_mode_t(mode));
@@ -476,7 +477,7 @@
 }
 
 Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
-        media::AudioPlaybackRate* _aidl_return)
+        media::audio::common::AudioPlaybackRate* _aidl_return)
 {
     audio_playback_rate_t localPlaybackRate{};
     status_t status = mTrack->getPlaybackRateParameters(&localPlaybackRate)
@@ -489,7 +490,7 @@
 }
 
 Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
-        const media::AudioPlaybackRate& playbackRate)
+        const media::audio::common::AudioPlaybackRate& playbackRate)
 {
     const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPlaybackRate_audio_playback_rate_t(playbackRate));
@@ -1916,9 +1917,7 @@
     }
 }
 
-binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
-        /*out*/ bool *ret) {
-    *ret = false;
+bool AudioFlinger::PlaybackThread::Track::AudioVibrationController::setMute(bool muted) {
     sp<ThreadBase> thread = mTrack->mThread.promote();
     if (thread != 0) {
         // Lock for updating mHapticPlaybackEnabled.
@@ -1926,27 +1925,22 @@
         PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
         if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
                 && playbackThread->mHapticChannelCount > 0) {
-            mTrack->setHapticPlaybackEnabled(false);
-            *ret = true;
+            mTrack->setHapticPlaybackEnabled(!muted);
+            return true;
         }
     }
+    return false;
+}
+
+binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
+        /*out*/ bool *ret) {
+    *ret = setMute(true);
     return binder::Status::ok();
 }
 
 binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::unmute(
         /*out*/ bool *ret) {
-    *ret = false;
-    sp<ThreadBase> thread = mTrack->mThread.promote();
-    if (thread != 0) {
-        // Lock for updating mHapticPlaybackEnabled.
-        Mutex::Autolock _l(thread->mLock);
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-        if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
-                && playbackThread->mHapticChannelCount > 0) {
-            mTrack->setHapticPlaybackEnabled(true);
-            *ret = true;
-        }
-    }
+    *ret = setMute(false);
     return binder::Status::ok();
 }
 
@@ -2356,15 +2350,9 @@
 }
 
 binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
-        std::vector<media::MicrophoneInfoData>* activeMicrophones) {
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
     ALOGV("%s()", __func__);
-    std::vector<media::MicrophoneInfo> mics;
-    status_t status = mRecordTrack->getActiveMicrophones(&mics);
-    activeMicrophones->resize(mics.size());
-    for (size_t i = 0; status == OK && i < mics.size(); ++i) {
-       status = mics[i].writeToParcelable(&activeMicrophones->at(i));
-    }
-    return binderStatusFromStatusT(status);
+    return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
 }
 
 binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
@@ -2684,7 +2672,7 @@
 }
 
 status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
-        std::vector<media::MicrophoneInfo>* activeMicrophones)
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones)
 {
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index cf1f64c..a62d3f0 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -194,6 +194,9 @@
             {AUDIO_FORMAT_E_AC3, {}},
             {AUDIO_FORMAT_DTS, {}},
             {AUDIO_FORMAT_DTS_HD, {}},
+            {AUDIO_FORMAT_DTS_HD_MA, {}},
+            {AUDIO_FORMAT_DTS_UHD, {}},
+            {AUDIO_FORMAT_DTS_UHD_P2, {}},
             {AUDIO_FORMAT_AAC_LC, {
                     AUDIO_FORMAT_AAC_HE_V1, AUDIO_FORMAT_AAC_HE_V2, AUDIO_FORMAT_AAC_ELD,
                     AUDIO_FORMAT_AAC_XHE}},
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index bb1699e..3b19e52 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -55,7 +55,7 @@
     status_t getAudioPolicyMix(audio_devices_t deviceType,
             const String8& address, sp<AudioPolicyMix> &policyMix) const;
 
-    status_t registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc);
+    status_t registerMix(const AudioMix& mix, const sp<SwAudioOutputDescriptor>& desc);
 
     status_t unregisterMix(const AudioMix& mix);
 
@@ -76,7 +76,7 @@
                               sp<AudioPolicyMix> &primaryMix,
                               std::vector<sp<AudioPolicyMix>> *secondaryMixes);
 
-    sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
+    sp<DeviceDescriptor> getDeviceAndMixForInputSource(const audio_attributes_t& attributes,
                                                        const DeviceVector &availableDeviceTypes,
                                                        uid_t uid,
                                                        sp<AudioPolicyMix> *policyMix) const;
@@ -124,7 +124,7 @@
     void dump(String8 *dst) const;
 
 private:
-    enum class MixMatchStatus { MATCH, NO_MATCH, INVALID_MIX };
+    enum class MixMatchStatus { MATCH, NO_MATCH };
     MixMatchStatus mixMatch(const AudioMix* mix, size_t mixIndex,
                             const audio_attributes_t& attributes,
                             const audio_config_base_t& config,
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index e142bef..56c0603 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "APM_AudioPolicyMix"
 //#define LOG_NDEBUG 0
 
+#include <algorithm>
 #include "AudioPolicyMix.h"
 #include "TypeConverter.h"
 #include "HwModule.h"
@@ -25,6 +26,89 @@
 #include <AudioOutputDescriptor.h>
 
 namespace android {
+namespace {
+
+// Returns true if the criterion matches.
+// The exclude criteria are handled in the same way as positive
+// ones - only condition is matched (the function will return
+// same result both for RULE_MATCH_X and RULE_EXCLUDE_X).
+bool isCriterionMatched(const AudioMixMatchCriterion& criterion,
+                        const audio_attributes_t& attr,
+                        const uid_t uid) {
+    uint32_t ruleWithoutExclusion = criterion.mRule & ~RULE_EXCLUSION_MASK;
+    switch(ruleWithoutExclusion) {
+        case RULE_MATCH_ATTRIBUTE_USAGE:
+            return criterion.mValue.mUsage == attr.usage;
+        case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
+            return criterion.mValue.mSource == attr.source;
+        case RULE_MATCH_UID:
+            return criterion.mValue.mUid == uid;
+        case RULE_MATCH_USERID:
+            {
+                userid_t userId = multiuser_get_user_id(uid);
+                return criterion.mValue.mUserId == userId;
+            }
+    }
+    ALOGE("Encountered invalid mix rule 0x%x", criterion.mRule);
+    return false;
+}
+
+// Returns true if vector of criteria is matched:
+// - If any of the exclude criteria is matched the criteria doesn't match.
+// - Otherwise, for each 'dimension' of positive rule present
+//   (usage, capture preset, uid, userid...) at least one rule must match
+//   for the criteria to match.
+bool areMixCriteriaMatched(const std::vector<AudioMixMatchCriterion>& criteria,
+                           const audio_attributes_t& attr,
+                           const uid_t uid) {
+    // If any of the exclusion criteria are matched the mix doesn't match.
+    auto isMatchingExcludeCriterion = [&](const AudioMixMatchCriterion& c) {
+        return c.isExcludeCriterion() && isCriterionMatched(c, attr, uid);
+    };
+    if (std::any_of(criteria.begin(), criteria.end(), isMatchingExcludeCriterion)) {
+        return false;
+    }
+
+    uint32_t presentPositiveRules = 0; // Bitmask of all present positive criteria.
+    uint32_t matchedPositiveRules = 0; // Bitmask of all matched positive criteria.
+    for (const auto& criterion : criteria) {
+        if (criterion.isExcludeCriterion()) {
+            continue;
+        }
+        presentPositiveRules |= criterion.mRule;
+        if (isCriterionMatched(criterion, attr, uid)) {
+            matchedPositiveRules |= criterion.mRule;
+        }
+    }
+    return presentPositiveRules == matchedPositiveRules;
+}
+
+// Consistency checks: for each "dimension" of rules (usage, uid...), we can
+// only have MATCH rules, or EXCLUDE rules in each dimension, not a combination.
+bool areMixCriteriaConsistent(const std::vector<AudioMixMatchCriterion>& criteria) {
+    std::set<uint32_t> positiveCriteria;
+    for (const AudioMixMatchCriterion& c : criteria) {
+        if (c.isExcludeCriterion()) {
+            continue;
+        }
+        positiveCriteria.insert(c.mRule);
+    }
+
+    auto isConflictingCriterion = [&positiveCriteria](const AudioMixMatchCriterion& c) {
+        uint32_t ruleWithoutExclusion = c.mRule & ~RULE_EXCLUSION_MASK;
+        return c.isExcludeCriterion() &&
+               (positiveCriteria.find(ruleWithoutExclusion) != positiveCriteria.end());
+    };
+    return std::none_of(criteria.begin(), criteria.end(), isConflictingCriterion);
+}
+
+template <typename Predicate>
+void EraseCriteriaIf(std::vector<AudioMixMatchCriterion>& v,
+                     const Predicate& predicate) {
+    v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end());
+}
+
+} // namespace
 
 void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const
 {
@@ -78,7 +162,8 @@
     }
 }
 
-status_t AudioPolicyMixCollection::registerMix(AudioMix mix, sp<SwAudioOutputDescriptor> desc)
+status_t AudioPolicyMixCollection::registerMix(const AudioMix& mix,
+                                               const sp<SwAudioOutputDescriptor>& desc)
 {
     for (size_t i = 0; i < size(); i++) {
         const sp<AudioPolicyMix>& registeredMix = itemAt(i);
@@ -89,12 +174,17 @@
             return BAD_VALUE;
         }
     }
-    sp<AudioPolicyMix> policyMix = new AudioPolicyMix(mix);
+    if (!areMixCriteriaConsistent(mix.mCriteria)) {
+        ALOGE("registerMix(): Mix contains inconsistent criteria "
+              "(MATCH & EXCLUDE criteria of the same type)");
+        return BAD_VALUE;
+    }
+    sp<AudioPolicyMix> policyMix = sp<AudioPolicyMix>::make(mix);
     add(policyMix);
     ALOGD("registerMix(): adding mix for dev=0x%x addr=%s",
             policyMix->mDeviceType, policyMix->mDeviceAddress.string());
 
-    if (desc != 0) {
+    if (desc != nullptr) {
         desc->mPolicyMix = policyMix;
         policyMix->setOutput(desc);
     }
@@ -177,15 +267,9 @@
             continue; // Primary output already found
         }
 
-        switch (mixMatch(policyMix.get(), i, attributes, config, uid)) {
-            case MixMatchStatus::INVALID_MIX:
-                // The mix has contradictory rules, ignore it
-                // TODO: reject invalid mix at registration
-                continue;
-            case MixMatchStatus::NO_MATCH:
-                ALOGV("%s: Mix %zu: does not match", __func__, i);
-                continue; // skip the mix
-            case MixMatchStatus::MATCH:;
+        if(mixMatch(policyMix.get(), i, attributes, config, uid) == MixMatchStatus::NO_MATCH) {
+            ALOGV("%s: Mix %zu: does not match", __func__, i);
+            continue; // skip the mix
         }
 
         if (primaryOutputMix) {
@@ -239,136 +323,19 @@
             return MixMatchStatus::NO_MATCH;
         }
 
-        int userId = (int) multiuser_get_user_id(uid);
-
-        // TODO if adding more player rules (currently only 2), make rule handling "generic"
-        //      as there is no difference in the treatment of usage- or uid-based rules
-        bool hasUsageMatchRules = false;
-        bool hasUsageExcludeRules = false;
-        bool usageMatchFound = false;
-        bool usageExclusionFound = false;
-
-        bool hasUidMatchRules = false;
-        bool hasUidExcludeRules = false;
-        bool uidMatchFound = false;
-        bool uidExclusionFound = false;
-
-        bool hasUserIdExcludeRules = false;
-        bool userIdExclusionFound = false;
-        bool hasUserIdMatchRules = false;
-        bool userIdMatchFound = false;
-
-
-        bool hasAddrMatch = false;
-
-        // iterate over all mix criteria to list what rules this mix contains
-        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
-            ALOGV(" getOutputForAttr: mix %zu: inspecting mix criteria %zu of %zu",
-                    mixIndex, j, mix->mCriteria.size());
-
-            // if there is an address match, prioritize that match
-            if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
-                    strncmp(attributes.tags + strlen("addr="),
-                            mix->mDeviceAddress.string(),
-                            AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
-                hasAddrMatch = true;
-                break;
-            }
-
-            switch (mix->mCriteria[j].mRule) {
-            case RULE_MATCH_ATTRIBUTE_USAGE:
-                ALOGV("\tmix has RULE_MATCH_ATTRIBUTE_USAGE for usage %d",
-                                            mix->mCriteria[j].mValue.mUsage);
-                hasUsageMatchRules = true;
-                if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
-                    // found one match against all allowed usages
-                    usageMatchFound = true;
-                }
-                break;
-            case RULE_EXCLUDE_ATTRIBUTE_USAGE:
-                ALOGV("\tmix has RULE_EXCLUDE_ATTRIBUTE_USAGE for usage %d",
-                        mix->mCriteria[j].mValue.mUsage);
-                hasUsageExcludeRules = true;
-                if (mix->mCriteria[j].mValue.mUsage == attributes.usage) {
-                    // found this usage is to be excluded
-                    usageExclusionFound = true;
-                }
-                break;
-            case RULE_MATCH_UID:
-                ALOGV("\tmix has RULE_MATCH_UID for uid %d", mix->mCriteria[j].mValue.mUid);
-                hasUidMatchRules = true;
-                if (mix->mCriteria[j].mValue.mUid == uid) {
-                    // found one UID match against all allowed UIDs
-                    uidMatchFound = true;
-                }
-                break;
-            case RULE_EXCLUDE_UID:
-                ALOGV("\tmix has RULE_EXCLUDE_UID for uid %d", mix->mCriteria[j].mValue.mUid);
-                hasUidExcludeRules = true;
-                if (mix->mCriteria[j].mValue.mUid == uid) {
-                    // found this UID is to be excluded
-                    uidExclusionFound = true;
-                }
-                break;
-            case RULE_MATCH_USERID:
-                ALOGV("\tmix has RULE_MATCH_USERID for userId %d",
-                    mix->mCriteria[j].mValue.mUserId);
-                hasUserIdMatchRules = true;
-                if (mix->mCriteria[j].mValue.mUserId == userId) {
-                    // found one userId match against all allowed userIds
-                    userIdMatchFound = true;
-                }
-                break;
-            case RULE_EXCLUDE_USERID:
-                ALOGV("\tmix has RULE_EXCLUDE_USERID for userId %d",
-                    mix->mCriteria[j].mValue.mUserId);
-                hasUserIdExcludeRules = true;
-                if (mix->mCriteria[j].mValue.mUserId == userId) {
-                    // found this userId is to be excluded
-                    userIdExclusionFound = true;
-                }
-                break;
-            default:
-                break;
-            }
-
-            // consistency checks: for each "dimension" of rules (usage, uid...), we can
-            // only have MATCH rules, or EXCLUDE rules in each dimension, not a combination
-            if (hasUsageMatchRules && hasUsageExcludeRules) {
-                ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_ATTRIBUTE_USAGE"
-                        " and RULE_EXCLUDE_ATTRIBUTE_USAGE in mix %zu", mixIndex);
-                return MixMatchStatus::INVALID_MIX;
-            }
-            if (hasUidMatchRules && hasUidExcludeRules) {
-                ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_UID"
-                        " and RULE_EXCLUDE_UID in mix %zu", mixIndex);
-                return MixMatchStatus::INVALID_MIX;
-            }
-            if (hasUserIdMatchRules && hasUserIdExcludeRules) {
-                ALOGE("getOutputForAttr: invalid combination of RULE_MATCH_USERID"
-                        " and RULE_EXCLUDE_USERID in mix %zu", mixIndex);
-                    return MixMatchStatus::INVALID_MIX;
-            }
-
-            if ((hasUsageExcludeRules && usageExclusionFound)
-                    || (hasUidExcludeRules && uidExclusionFound)
-                    || (hasUserIdExcludeRules && userIdExclusionFound)) {
-                break; // stop iterating on criteria because an exclusion was found (will fail)
-            }
-        }//iterate on mix criteria
-
-        // determine if exiting on success (or implicit failure as desc is 0)
-        if (hasAddrMatch ||
-                !((hasUsageExcludeRules && usageExclusionFound) ||
-                  (hasUsageMatchRules && !usageMatchFound)  ||
-                  (hasUidExcludeRules && uidExclusionFound) ||
-                  (hasUidMatchRules && !uidMatchFound) ||
-                  (hasUserIdExcludeRules && userIdExclusionFound) ||
-                  (hasUserIdMatchRules && !userIdMatchFound))) {
+        // if there is an address match, prioritize that match
+        if (strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
+                strncmp(attributes.tags + strlen("addr="),
+                        mix->mDeviceAddress.string(),
+                        AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0) {
             ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
             return MixMatchStatus::MATCH;
         }
 
+        if (areMixCriteriaMatched(mix->mCriteria, attributes, uid)) {
+            ALOGV("\tgetOutputForAttr will use mix %zu", mixIndex);
+            return MixMatchStatus::MATCH;
+        }
     } else if (mix->mMixType == MIX_TYPE_RECORDERS) {
         if (attributes.usage == AUDIO_USAGE_VIRTUAL_SOURCE &&
                 strncmp(attributes.tags, "addr=", strlen("addr=")) == 0 &&
@@ -399,7 +366,7 @@
 }
 
 sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForInputSource(
-        audio_source_t inputSource,
+        const audio_attributes_t& attributes,
         const DeviceVector &availDevices,
         uid_t uid,
         sp<AudioPolicyMix> *policyMix) const
@@ -409,28 +376,17 @@
         if (mix->mMixType != MIX_TYPE_RECORDERS) {
             continue;
         }
-        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
-            if ((RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
-                    mix->mCriteria[j].mValue.mSource == inputSource) ||
-               (RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET == mix->mCriteria[j].mRule &&
-                    mix->mCriteria[j].mValue.mSource != inputSource) ||
-               (RULE_MATCH_UID == mix->mCriteria[j].mRule &&
-                    mix->mCriteria[j].mValue.mUid == uid) ||
-               (RULE_EXCLUDE_UID == mix->mCriteria[j].mRule &&
-                    mix->mCriteria[j].mValue.mUid != uid)) {
-                // assuming PolicyMix only for remote submix for input
-                // so mix->mDeviceType can only be AUDIO_DEVICE_OUT_REMOTE_SUBMIX
-                audio_devices_t device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
-                auto mixDevice =
-                        availDevices.getDevice(device, mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
+        if (areMixCriteriaMatched(mix->mCriteria, attributes, uid)) {
+            // Assuming PolicyMix only for remote submix for input
+            // so mix->mDeviceType can only be AUDIO_DEVICE_OUT_REMOTE_SUBMIX.
+            auto mixDevice = availDevices.getDevice(AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+             mix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
                 if (mixDevice != nullptr) {
                     if (policyMix != nullptr) {
                         *policyMix = mix;
                     }
                     return mixDevice;
                 }
-                break;
-            }
         }
     }
     return nullptr;
@@ -501,7 +457,7 @@
     //     AND it doesn't have a "match uid" rule
     //   THEN add a rule to exclude the uid
     for (size_t i = 0; i < size(); i++) {
-        const AudioPolicyMix *mix = itemAt(i).get();
+        AudioPolicyMix *mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
@@ -531,27 +487,16 @@
 status_t AudioPolicyMixCollection::removeUidDeviceAffinities(uid_t uid) {
     // for each player mix: remove existing rules that match or exclude this uid
     for (size_t i = 0; i < size(); i++) {
-        bool foundUidRule = false;
-        const AudioPolicyMix *mix = itemAt(i).get();
+        AudioPolicyMix *mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
-        std::vector<size_t> criteriaToRemove;
-        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
-            const uint32_t rule = mix->mCriteria[j].mRule;
-            // is this rule excluding the uid? (not considering uid match rules
-            // as those are not used for uid-device affinity)
-            if (rule == RULE_EXCLUDE_UID
-                    && uid == mix->mCriteria[j].mValue.mUid) {
-                foundUidRule = true;
-                criteriaToRemove.insert(criteriaToRemove.begin(), j);
-            }
-        }
-        if (foundUidRule) {
-            for (size_t j = 0; j < criteriaToRemove.size(); j++) {
-                mix->mCriteria.removeAt(criteriaToRemove[j]);
-            }
-        }
+
+        // is this rule excluding the uid? (not considering uid match rules
+        // as those are not used for uid-device affinity)
+        EraseCriteriaIf(mix->mCriteria, [uid](const AudioMixMatchCriterion& c) {
+            return c.mRule == RULE_EXCLUDE_UID && c.mValue.mUid == uid;
+        });
     }
     return NO_ERROR;
 }
@@ -586,7 +531,7 @@
     //    "match userId" rule for this userId, return an error
     //    (adding a userId-device affinity would result in contradictory rules)
     for (size_t i = 0; i < size(); i++) {
-        const AudioPolicyMix* mix = itemAt(i).get();
+        AudioPolicyMix* mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
@@ -603,7 +548,7 @@
     //     AND it doesn't have a "match userId" rule
     //   THEN add a rule to exclude the userId
     for (size_t i = 0; i < size(); i++) {
-        const AudioPolicyMix *mix = itemAt(i).get();
+        AudioPolicyMix *mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
@@ -633,27 +578,16 @@
 status_t AudioPolicyMixCollection::removeUserIdDeviceAffinities(int userId) {
     // for each player mix: remove existing rules that match or exclude this userId
     for (size_t i = 0; i < size(); i++) {
-        bool foundUserIdRule = false;
-        const AudioPolicyMix *mix = itemAt(i).get();
+        AudioPolicyMix *mix = itemAt(i).get();
         if (!mix->isDeviceAffinityCompatible()) {
             continue;
         }
-        std::vector<size_t> criteriaToRemove;
-        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
-            const uint32_t rule = mix->mCriteria[j].mRule;
-            // is this rule excluding the userId? (not considering userId match rules
-            // as those are not used for userId-device affinity)
-            if (rule == RULE_EXCLUDE_USERID
-                    && userId == mix->mCriteria[j].mValue.mUserId) {
-                foundUserIdRule = true;
-                criteriaToRemove.insert(criteriaToRemove.begin(), j);
-            }
-        }
-        if (foundUserIdRule) {
-            for (size_t j = 0; j < criteriaToRemove.size(); j++) {
-                mix->mCriteria.removeAt(criteriaToRemove[j]);
-            }
-        }
+
+        // is this rule excluding the userId? (not considering userId match rules
+        // as those are not used for userId-device affinity)
+        EraseCriteriaIf(mix->mCriteria, [userId](const AudioMixMatchCriterion& c) {
+            return c.mRule == RULE_EXCLUDE_USERID && c.mValue.mUserId == userId;
+        });
     }
     return NO_ERROR;
 }
diff --git a/services/audiopolicy/config/surround_sound_configuration_aidl.xml b/services/audiopolicy/config/surround_sound_configuration_aidl.xml
new file mode 100644
index 0000000..cf15711
--- /dev/null
+++ b/services/audiopolicy/config/surround_sound_configuration_aidl.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- 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.
+-->
+<surroundSound>
+  <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+       There must be a corresponding Java ENCODING_... constant defined in AudioFormat.java,
+       and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+       need a dedicated Surround Settings dialog entry, a subformats list has to be used. -->
+  <formats>
+    <format name="AUDIO_FORMAT_AC3" />
+    <format name="AUDIO_FORMAT_E_AC3" />
+    <format name="AUDIO_FORMAT_E_AC3_JOC" />
+    <format name="AUDIO_FORMAT_DOLBY_TRUEHD" />
+    <format name="AUDIO_FORMAT_DTS" />
+    <format name="AUDIO_FORMAT_DTS_HD" />
+    <format name="AUDIO_FORMAT_DTS_HD_MA" />
+    <format name="AUDIO_FORMAT_DTS_UHD" />
+    <format name="AUDIO_FORMAT_DTS_UHD_P2" />
+    <format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
+    <format name="AUDIO_FORMAT_AC4" />
+  </formats>
+</surroundSound>
diff --git a/services/audiopolicy/engine/common/src/VolumeCurve.cpp b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
index 8aa4b08..fccbc60 100644
--- a/services/audiopolicy/engine/common/src/VolumeCurve.cpp
+++ b/services/audiopolicy/engine/common/src/VolumeCurve.cpp
@@ -52,7 +52,7 @@
             volIdx = volIndexMin;
         } else {
             // This would result in a divide-by-zero below
-            ALOG_ASSERT(volIndexmin != volIndexMax, "Invalid volume index range & value: 0");
+            ALOG_ASSERT(volIndexMin != volIndexMax, "Invalid volume index range & value: 0");
             return NAN;
         }
     } else {
diff --git a/services/audiopolicy/engineconfigurable/src/Engine.cpp b/services/audiopolicy/engineconfigurable/src/Engine.cpp
index 3d74920..2831a9b 100644
--- a/services/audiopolicy/engineconfigurable/src/Engine.cpp
+++ b/services/audiopolicy/engineconfigurable/src/Engine.cpp
@@ -333,7 +333,7 @@
         return device;
     }
 
-    device = policyMixes.getDeviceAndMixForInputSource(attr.source,
+    device = policyMixes.getDeviceAndMixForInputSource(attr,
                                                        availableInputDevices,
                                                        uid,
                                                        mix);
diff --git a/services/audiopolicy/engineconfigurable/tools/Android.bp b/services/audiopolicy/engineconfigurable/tools/Android.bp
index 40efb3d..b6089b7 100644
--- a/services/audiopolicy/engineconfigurable/tools/Android.bp
+++ b/services/audiopolicy/engineconfigurable/tools/Android.bp
@@ -21,36 +21,23 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
-python_defaults {
-    name: "tools_default",
-    version: {
-        py2: {
-            enabled: false,
-        },
-        py3: {
-            enabled: true,
-        },
-    },
-}
-
 //##################################################################################################
 // Tools for audio policy engine criterion type configuration file
 //
 python_binary_host {
-    name: "buildPolicyCriterionTypes.py",
+    name: "buildPolicyCriterionTypes",
     main: "buildPolicyCriterionTypes.py",
     srcs: [
         "buildPolicyCriterionTypes.py",
     ],
-    defaults: ["tools_default"],
 }
 
 genrule_defaults {
     name: "buildpolicycriteriontypesrule",
-    tools: ["buildPolicyCriterionTypes.py"],
+    tools: ["buildPolicyCriterionTypes"],
     cmd: "cp $(locations :audio_policy_configuration_files) $(genDir)/. && " +
          "cp $(location :audio_policy_configuration_top_file) $(genDir)/audio_policy_configuration.xml && " +
-         "$(location buildPolicyCriterionTypes.py) " +
+         "$(location buildPolicyCriterionTypes) " +
          " --androidaudiobaseheader $(location :libaudio_system_audio_base) " +
          " --androidaudiocommonbaseheader $(location :libaudio_system_audio_common_base) " +
          "--audiopolicyconfigurationfile $(genDir)/audio_policy_configuration.xml " +
@@ -72,12 +59,11 @@
 // Tools for audio policy engine parameter framework configurable domains
 //
 python_binary_host {
-    name: "domainGeneratorPolicy.py",
+    name: "domainGeneratorPolicy",
     main: "domainGeneratorPolicy.py",
     srcs: [
         "domainGeneratorPolicy.py",
     ],
-    defaults: ["tools_default"],
     libs: [
         "EddParser.py",
         "hostConfig.py",
@@ -91,13 +77,13 @@
 genrule_defaults {
     name: "domaingeneratorpolicyrule",
     tools: [
-        "domainGeneratorPolicy.py",
+        "domainGeneratorPolicy",
         "domainGeneratorConnector",
     ],
     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 && " +
-         "$(location domainGeneratorPolicy.py) " +
+         "$(location domainGeneratorPolicy) " +
          "--validate " +
          "--domain-generator-tool $(location domainGeneratorConnector) " +
          "--toplevel-config $(genDir)/top_level " +
@@ -121,19 +107,18 @@
 // Tools for policy parameter-framework product strategies structure file generation
 //
 python_binary_host {
-    name: "buildStrategiesStructureFile.py",
+    name: "buildStrategiesStructureFile",
     main: "buildStrategiesStructureFile.py",
     srcs: [
         "buildStrategiesStructureFile.py",
     ],
-    defaults: ["tools_default"],
 }
 
 genrule_defaults {
     name: "buildstrategiesstructurerule",
-    tools: ["buildStrategiesStructureFile.py"],
+    tools: ["buildStrategiesStructureFile"],
     cmd: "cp $(locations :audio_policy_engine_configuration_files) $(genDir) && ls -l $(genDir) &&"+
-         "$(location buildStrategiesStructureFile.py) " +
+         "$(location buildStrategiesStructureFile) " +
          "--audiopolicyengineconfigurationfile $(genDir)/audio_policy_engine_configuration.xml "+
          "--productstrategiesstructurefile $(location :product_strategies_structure_template) " +
          "--outputfile $(out)",
@@ -149,18 +134,17 @@
 // Tools for policy parameter-framework common type structure file generation
 //
 python_binary_host {
-    name: "buildCommonTypesStructureFile.py",
+    name: "buildCommonTypesStructureFile",
     main: "buildCommonTypesStructureFile.py",
     srcs: [
         "buildCommonTypesStructureFile.py",
     ],
-    defaults: ["tools_default"],
 }
 
 genrule_defaults {
     name: "buildcommontypesstructurerule",
-    tools: ["buildCommonTypesStructureFile.py"],
-    cmd: "$(location buildCommonTypesStructureFile.py) " +
+    tools: ["buildCommonTypesStructureFile"],
+    cmd: "$(location buildCommonTypesStructureFile) " +
          "--androidaudiobaseheader $(location :libaudio_system_audio_base) " +
          "--commontypesstructure $(location :common_types_structure_template) " +
          "--outputfile $(out)",
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 52b9826..649c63f 100644
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -779,7 +779,7 @@
         return device;
     }
 
-    device = policyMixes.getDeviceAndMixForInputSource(attr.source,
+    device = policyMixes.getDeviceAndMixForInputSource(attr,
                                                        availableInputDevices,
                                                        uid,
                                                        mix);
diff --git a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
index 48f7410..28268c9 100644
--- a/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
+++ b/services/audiopolicy/fuzzer/audiopolicy_fuzzer.cpp
@@ -544,10 +544,11 @@
 status_t AudioPolicyManagerFuzzerDynamicPolicy::addPolicyMix(
     int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress,
     const audio_config_t &audioConfig, const std::vector<PolicyMixTuple> &rules) {
-    Vector<AudioMixMatchCriterion> myMixMatchCriteria;
+    std::vector<AudioMixMatchCriterion> myMixMatchCriteria;
 
+    myMixMatchCriteria.reserve(rules.size());
     for (const auto &rule : rules) {
-        myMixMatchCriteria.add(
+        myMixMatchCriteria.push_back(
             AudioMixMatchCriterion(std::get<0>(rule), std::get<1>(rule), std::get<2>(rule)));
     }
 
diff --git a/services/audiopolicy/managerdefault/Android.bp b/services/audiopolicy/managerdefault/Android.bp
index 4b4817e..6e34eb0 100644
--- a/services/audiopolicy/managerdefault/Android.bp
+++ b/services/audiopolicy/managerdefault/Android.bp
@@ -10,6 +10,10 @@
 cc_library_shared {
     name: "libaudiopolicymanagerdefault",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     srcs: [
         "AudioPolicyManager.cpp",
         "EngineLibrary.cpp",
@@ -36,7 +40,6 @@
         "libaudiopolicyenginedefault",
         "framework-permission-aidl-cpp",
         "libaudioclient_aidl_conversion",
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
     ],
 
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8d00a3d..24c003e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -68,16 +68,6 @@
 // media / notification / system volume.
 constexpr float IN_CALL_EARPIECE_HEADROOM_DB = 3.f;
 
-// Compressed formats for MSD module, ordered from most preferred to least preferred.
-static const std::vector<audio_format_t> msdCompressedFormatsOrder = {{
-        AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
-        AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
-// Channel masks for MSD module, 3D > 2D > 1D ordering (most preferred to least preferred).
-static const std::vector<audio_channel_mask_t> msdSurroundChannelMasksOrder = {{
-        AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
-        AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
-        AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
-
 template <typename T>
 bool operator== (const SortedVector<T> &left, const SortedVector<T> &right)
 {
@@ -114,7 +104,7 @@
                                                       const char* device_address,
                                                       const char* device_name,
                                                       audio_format_t encodedFormat) {
-    media::AudioPort aidlPort;
+    media::AudioPortFw aidlPort;
     if (status_t status = deviceToAudioPort(device, device_address, device_name, &aidlPort);
         status == OK) {
         return setDeviceConnectionState(state, aidlPort.hal, encodedFormat);
@@ -140,8 +130,6 @@
 status_t AudioPolicyManager::setDeviceConnectionStateInt(
         audio_policy_dev_state_t state, const android::media::audio::common::AudioPort& port,
         audio_format_t encodedFormat) {
-    // TODO: b/211601178 Forward 'port' to Audio HAL via mHwModules. For now, only device_type,
-    // device_address and device_name are forwarded.
     if (port.ext.getTag() != AudioPortExt::device) {
         return BAD_VALUE;
     }
@@ -160,7 +148,13 @@
     sp<DeviceDescriptor> device = mHwModules.getDeviceDescriptor(
             device_type, device_address.c_str(), device_name, encodedFormat,
             state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
-    return device ? setDeviceConnectionStateInt(device, state) : INVALID_OPERATION;
+    if (device == nullptr) {
+        return INVALID_OPERATION;
+    }
+    if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+        device->setExtraAudioDescriptors(port.extraAudioDescriptors);
+    }
+    return setDeviceConnectionStateInt(device, state);
 }
 
 status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceType,
@@ -168,7 +162,7 @@
                                                          const char* device_address,
                                                          const char* device_name,
                                                          audio_format_t encodedFormat) {
-    media::AudioPort aidlPort;
+    media::AudioPortFw aidlPort;
     if (status_t status = deviceToAudioPort(deviceType, device_address, device_name, &aidlPort);
         status == OK) {
         return setDeviceConnectionStateInt(state, aidlPort.hal, encodedFormat);
@@ -450,7 +444,7 @@
 
 status_t AudioPolicyManager::deviceToAudioPort(audio_devices_t device, const char* device_address,
                                                const char* device_name,
-                                               media::AudioPort* aidlPort) {
+                                               media::AudioPortFw* aidlPort) {
     DeviceDescriptorBase devDescr(device, device_address);
     devDescr.setName(device_name);
     return devDescr.writeToParcelable(aidlPort);
@@ -602,7 +596,10 @@
         audioDeviceSet = getAudioDeviceOutAllA2dpSet();
         break;
     case AUDIO_DEVICE_OUT_BLE_HEADSET:
-        audioDeviceSet = getAudioDeviceOutAllBleSet();
+        audioDeviceSet = getAudioDeviceOutLeAudioUnicastSet();
+        break;
+    case AUDIO_DEVICE_OUT_BLE_BROADCAST:
+        audioDeviceSet = getAudioDeviceOutLeAudioBroadcastSet();
         break;
     default:
         ALOGE("%s() device type 0x%08x not supported", __func__, device);
@@ -1034,7 +1031,7 @@
 
              // when searching for direct outputs, if several profiles are compatible, give priority
              // to one with offload capability
-             if (profile != 0 && 
+             if (profile != 0 &&
                  ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) {
                 continue;
              }
@@ -1534,6 +1531,10 @@
     if ((*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) != 0) {
         return AUDIO_IO_HANDLE_NONE;
     }
+    // A request for Tuner cannot fallback to a mixed output
+    if ((directConfig.offload_info.content_id || directConfig.offload_info.sync_id)) {
+        return AUDIO_IO_HANDLE_NONE;
+    }
 
     // ignoring channel mask due to downmix capability in mixer
 
@@ -1641,10 +1642,28 @@
         const AudioProfileVector &sourceProfiles, const AudioProfileVector &sinkProfiles,
         audio_port_config *sourceConfig, audio_port_config *sinkConfig) const
 {
+    // Compressed formats for MSD module, ordered from most preferred to least preferred.
+    static const std::vector<audio_format_t> formatsOrder = {{
+            AUDIO_FORMAT_IEC60958, AUDIO_FORMAT_MAT_2_1, AUDIO_FORMAT_MAT_2_0, AUDIO_FORMAT_E_AC3,
+            AUDIO_FORMAT_AC3, AUDIO_FORMAT_PCM_16_BIT }};
+    static const std::vector<audio_channel_mask_t> channelMasksOrder = [](){
+        // Channel position masks for MSD module, 3D > 2D > 1D ordering (most preferred to least
+        // preferred).
+        std::vector<audio_channel_mask_t> masks = {{
+            AUDIO_CHANNEL_OUT_3POINT1POINT2, AUDIO_CHANNEL_OUT_3POINT0POINT2,
+            AUDIO_CHANNEL_OUT_2POINT1POINT2, AUDIO_CHANNEL_OUT_2POINT0POINT2,
+            AUDIO_CHANNEL_OUT_5POINT1, AUDIO_CHANNEL_OUT_STEREO }};
+        // insert index masks (higher counts most preferred) as preferred over position masks
+        for (int i = 1; i <= AUDIO_CHANNEL_COUNT_MAX; i++) {
+            masks.insert(
+                    masks.begin(), audio_channel_mask_for_index_assignment_from_count(i));
+        }
+        return masks;
+    }();
+
     struct audio_config_base bestSinkConfig;
-    status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles,
-            msdCompressedFormatsOrder, msdSurroundChannelMasksOrder,
-            true /*preferHigherSamplingRates*/, bestSinkConfig);
+    status_t result = findBestMatchingOutputConfig(sourceProfiles, sinkProfiles, formatsOrder,
+            channelMasksOrder, true /*preferHigherSamplingRates*/, bestSinkConfig);
     if (result != NO_ERROR) {
         ALOGD("%s() no matching config found for sink, hwAvSync: %d",
                 __func__, hwAvSync);
@@ -1666,7 +1685,10 @@
     }
     sourceConfig->sample_rate = bestSinkConfig.sample_rate;
     // Specify exact channel mask to prevent guessing by bit count in PatchPanel.
-    sourceConfig->channel_mask = audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
+    sourceConfig->channel_mask =
+            audio_channel_mask_get_representation(bestSinkConfig.channel_mask)
+            == AUDIO_CHANNEL_REPRESENTATION_INDEX ?
+            bestSinkConfig.channel_mask : audio_channel_mask_out_to_in(bestSinkConfig.channel_mask);
     sourceConfig->format = bestSinkConfig.format;
     // Copy input stream directly without any processing (e.g. resampling).
     sourceConfig->flags.input = static_cast<audio_input_flags_t>(
@@ -3168,7 +3190,7 @@
     // stream by the engine.
     DeviceTypeSet deviceTypes = {device};
     if (device == AUDIO_DEVICE_OUT_DEFAULT_FOR_VOLUME) {
-        DeviceTypeSet deviceTypes = mEngine->getOutputDevicesForAttributes(
+        deviceTypes = mEngine->getOutputDevicesForAttributes(
                 attr, nullptr, true /*fromCache*/).types();
     }
     return getVolumeIndex(getVolumeCurves(attr), index, deviceTypes);
@@ -3178,7 +3200,7 @@
                                             int &index,
                                             const DeviceTypeSet& deviceTypes) const
 {
-    if (isSingleDeviceType(deviceTypes, audio_is_output_device)) {
+    if (!isSingleDeviceType(deviceTypes, audio_is_output_device)) {
         return BAD_VALUE;
     }
     index = curves.getVolumeIndex(deviceTypes);
@@ -5628,6 +5650,17 @@
         return status;
     }
 
+    // If microphones address is empty, set it according to device type
+    for (size_t i = 0; i < mInputDevicesAll.size(); i++) {
+        if (mInputDevicesAll[i]->address().empty()) {
+            if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
+                mInputDevicesAll[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
+            } else if (mInputDevicesAll[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
+                mInputDevicesAll[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
+            }
+        }
+    }
+
     mEngine->updateDeviceSelectionCache();
     mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
         mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
@@ -5642,17 +5675,6 @@
                  mDefaultOutputDevice->toString().c_str());
         status = NO_INIT;
     }
-    // If microphones address is empty, set it according to device type
-    for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
-        if (mAvailableInputDevices[i]->address().empty()) {
-            if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
-                mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
-            } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
-                mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
-            }
-        }
-    }
-
     ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
 
     // Silence ALOGV statements
@@ -7345,7 +7367,8 @@
     // if sco and call follow same curves, bypass forceUseForComm
     if ((callVolSrc != btScoVolSrc) &&
             ((isVoiceVolSrc && isScoRequested) ||
-             (isBtScoVolSrc && !(isScoRequested || isHAUsed)))) {
+             (isBtScoVolSrc && !(isScoRequested || isHAUsed))) &&
+            !isSingleDeviceType(deviceTypes, AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
         ALOGV("%s cannot set volume group %d volume when is%srequested for comm", __func__,
              volumeSource, isScoRequested ? " " : " not ");
         // Do not return an error here as AudioService will always set both voice call
@@ -7866,6 +7889,9 @@
 
     addOutput(output, desc);
 
+    sp<DeviceDescriptor> speaker = mAvailableOutputDevices.getDevice(
+            AUDIO_DEVICE_OUT_SPEAKER, String8(""), AUDIO_FORMAT_DEFAULT);
+
     if (audio_is_remote_submix_device(deviceType) && address != "0") {
         sp<AudioPolicyMix> policyMix;
         if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix) == NO_ERROR) {
@@ -7876,13 +7902,13 @@
                     address.string());
         }
 
-    } else if (hasPrimaryOutput() && profile->getModule()
-                != mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)
+    } else if (hasPrimaryOutput() && speaker != nullptr
+            && mPrimaryOutput->supportsDevice(speaker) && !desc->supportsDevice(speaker)
             && ((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) {
         // no duplicated output for:
         // - direct outputs
         // - outputs used by dynamic policy mixes
-        // - outputs opened on the primary HW module
+        // - outputs that supports SPEAKER while the primary output does not.
         audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
 
         //TODO: configure audio effect output stage here
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index a69e088..8466d097 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -1016,7 +1016,7 @@
 
         // Called by setDeviceConnectionState()
         status_t deviceToAudioPort(audio_devices_t deviceType, const char* device_address,
-                                   const char* device_name, media::AudioPort* aidPort);
+                                   const char* device_name, media::AudioPortFw* aidPort);
         bool isMsdPatch(const audio_patch_handle_t &handle) const;
 
 private:
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index cdad9a6..4c19d40 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -10,6 +10,10 @@
 cc_library_shared {
     name: "libaudiopolicyservice",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     srcs: [
         "AudioPolicyClientImpl.cpp",
         "AudioPolicyEffects.cpp",
@@ -49,7 +53,6 @@
         "libshmemcompat",
         "libutils",
         "libstagefright_foundation",
-        "android.media.audio.common.types-V1-cpp",
         "audioclient-types-aidl-cpp",
         "audioflinger-aidl-cpp",
         "audiopolicy-aidl-cpp",
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 70fdfcb..c7a60c2 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -127,7 +127,8 @@
             attributionSource.packageName = "android";
             attributionSource.token = sp<BBinder>::make();
             sp<AudioEffect> fx = new AudioEffect(attributionSource);
-            fx->set(NULL, &effect->mUuid, -1, 0, 0, audioSession, input);
+            fx->set(nullptr /*type */, &effect->mUuid, -1 /* priority */, nullptr /* callback */,
+                    audioSession, input);
             status_t status = fx->initCheck();
             if (status != NO_ERROR && status != ALREADY_EXISTS) {
                 ALOGW("addInputEffects(): failed to create Fx %s on source %d",
@@ -279,7 +280,8 @@
             attributionSource.packageName = "android";
             attributionSource.token = sp<BBinder>::make();
             sp<AudioEffect> fx = new AudioEffect(attributionSource);
-            fx->set(NULL, &effect->mUuid, 0, 0, 0, audioSession, output);
+            fx->set(nullptr /* type */, &effect->mUuid, 0 /* priority */, nullptr /* callback */,
+                    audioSession, output);
             status_t status = fx->initCheck();
             if (status != NO_ERROR && status != ALREADY_EXISTS) {
                 ALOGE("addOutputSessionEffects(): failed to create Fx  %s on session %d",
@@ -984,8 +986,8 @@
             attributionSource.packageName = "android";
             attributionSource.token = sp<BBinder>::make();
             sp<AudioEffect> fx = new AudioEffect(attributionSource);
-            fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0, nullptr,
-                    nullptr, AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
+            fx->set(EFFECT_UUID_NULL, &effectDesc->mUuid, 0 /* priority */, nullptr /* callback */,
+                    AUDIO_SESSION_DEVICE, AUDIO_IO_HANDLE_NONE,
                     AudioDeviceTypeAddr{deviceEffects->getDeviceType(),
                                         deviceEffects->getDeviceAddress()});
             status_t status = fx->initCheck();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 49224c5..fdf5787 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -1485,7 +1485,7 @@
 
 Status AudioPolicyService::listAudioPorts(media::AudioPortRole roleAidl,
                                           media::AudioPortType typeAidl, Int* count,
-                                          std::vector<media::AudioPort>* portsAidl,
+                                          std::vector<media::AudioPortFw>* portsAidl,
                                           int32_t* _aidl_return) {
     audio_port_role_t role = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioPortRole_audio_port_role_t(roleAidl));
@@ -1510,14 +1510,14 @@
     numPortsReq = std::min(numPortsReq, num_ports);
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             convertRange(ports.get(), ports.get() + numPortsReq, std::back_inserter(*portsAidl),
-                         legacy2aidl_audio_port_v7_AudioPort)));
+                         legacy2aidl_audio_port_v7_AudioPortFw)));
     count->value = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(num_ports));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(generation));
     return Status::ok();
 }
 
 Status AudioPolicyService::getAudioPort(int portId,
-                                        media::AudioPort* _aidl_return) {
+                                        media::AudioPortFw* _aidl_return) {
     audio_port_v7 port{ .id = portId };
     Mutex::Autolock _l(mLock);
     if (mAudioPolicyManager == NULL) {
@@ -1525,14 +1525,15 @@
     }
     AutoCallerClear acc;
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(mAudioPolicyManager->getAudioPort(&port)));
-    *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPort(port));
+    *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(legacy2aidl_audio_port_v7_AudioPortFw(port));
     return Status::ok();
 }
 
-Status AudioPolicyService::createAudioPatch(const media::AudioPatch& patchAidl, int32_t handleAidl,
+Status AudioPolicyService::createAudioPatch(const media::AudioPatchFw& patchAidl,
+                                            int32_t handleAidl,
                                             int32_t* _aidl_return) {
     audio_patch patch = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioPatch_audio_patch(patchAidl));
+            aidl2legacy_AudioPatchFw_audio_patch(patchAidl));
     audio_patch_handle_t handle = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_int32_t_audio_port_handle_t(handleAidl));
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(AudioValidator::validateAudioPatch(patch)));
@@ -1570,7 +1571,7 @@
 }
 
 Status AudioPolicyService::listAudioPatches(Int* count,
-                                            std::vector<media::AudioPatch>* patchesAidl,
+                                            std::vector<media::AudioPatchFw>* patchesAidl,
                                             int32_t* _aidl_return) {
     unsigned int num_patches = VALUE_OR_RETURN_BINDER_STATUS(
             convertIntegral<unsigned int>(count->value));
@@ -1591,16 +1592,16 @@
     numPatchesReq = std::min(numPatchesReq, num_patches);
     RETURN_IF_BINDER_ERROR(binderStatusFromStatusT(
             convertRange(patches.get(), patches.get() + numPatchesReq,
-                         std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatch)));
+                         std::back_inserter(*patchesAidl), legacy2aidl_audio_patch_AudioPatchFw)));
     count->value = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(num_patches));
     *_aidl_return = VALUE_OR_RETURN_BINDER_STATUS(convertIntegral<int32_t>(generation));
     return Status::ok();
 }
 
-Status AudioPolicyService::setAudioPortConfig(const media::AudioPortConfig& configAidl)
+Status AudioPolicyService::setAudioPortConfig(const media::AudioPortConfigFw& configAidl)
 {
     audio_port_config config = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioPortConfig_audio_port_config(configAidl));
+            aidl2legacy_AudioPortConfigFw_audio_port_config(configAidl));
     RETURN_IF_BINDER_ERROR(
             binderStatusFromStatusT(AudioValidator::validateAudioPortConfig(config)));
 
@@ -1770,11 +1771,11 @@
     return binderStatusFromStatusT(mAudioPolicyManager->removeUserIdDeviceAffinities(userId));
 }
 
-Status AudioPolicyService::startAudioSource(const media::AudioPortConfig& sourceAidl,
+Status AudioPolicyService::startAudioSource(const media::AudioPortConfigFw& sourceAidl,
                                             const media::AudioAttributesInternal& attributesAidl,
                                             int32_t* _aidl_return) {
     audio_port_config source = VALUE_OR_RETURN_BINDER_STATUS(
-            aidl2legacy_AudioPortConfig_audio_port_config(sourceAidl));
+            aidl2legacy_AudioPortConfigFw_audio_port_config(sourceAidl));
     audio_attributes_t attributes = VALUE_OR_RETURN_BINDER_STATUS(
             aidl2legacy_AudioAttributesInternal_audio_attributes_t(attributesAidl));
     audio_port_handle_t portId;
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 21fa82e..281785e 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1733,6 +1733,7 @@
 }
 
 bool AudioPolicyService::UidPolicy::isA11yOnTop() {
+    Mutex::Autolock _l(mLock);
     for (const auto &uid : mCachedUids) {
         if (!isA11yUid(uid.first)) {
             continue;
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index a87d871..860bd18 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -172,16 +172,16 @@
                                            const media::AudioAttributesInternal& attributes,
                                            bool* _aidl_return) override;
     binder::Status listAudioPorts(media::AudioPortRole role, media::AudioPortType type,
-                                  Int* count, std::vector<media::AudioPort>* ports,
+                                  Int* count, std::vector<media::AudioPortFw>* ports,
                                   int32_t* _aidl_return) override;
     binder::Status getAudioPort(int portId,
-                                media::AudioPort* _aidl_return) override;
-    binder::Status createAudioPatch(const media::AudioPatch& patch, int32_t handle,
+                                media::AudioPortFw* _aidl_return) override;
+    binder::Status createAudioPatch(const media::AudioPatchFw& patch, int32_t handle,
                                     int32_t* _aidl_return) override;
     binder::Status releaseAudioPatch(int32_t handle) override;
-    binder::Status listAudioPatches(Int* count, std::vector<media::AudioPatch>* patches,
+    binder::Status listAudioPatches(Int* count, std::vector<media::AudioPatchFw>* patches,
                                     int32_t* _aidl_return) override;
-    binder::Status setAudioPortConfig(const media::AudioPortConfig& config) override;
+    binder::Status setAudioPortConfig(const media::AudioPortConfigFw& config) override;
     binder::Status registerClient(const sp<media::IAudioPolicyServiceClient>& client) override;
     binder::Status setAudioPortCallbacksEnabled(bool enabled) override;
     binder::Status setAudioVolumeGroupCallbacksEnabled(bool enabled) override;
@@ -197,7 +197,7 @@
             int32_t userId,
             const std::vector<AudioDevice>& devices) override;
     binder::Status removeUserIdDeviceAffinities(int32_t userId) override;
-    binder::Status startAudioSource(const media::AudioPortConfig& source,
+    binder::Status startAudioSource(const media::AudioPortConfigFw& source,
                                     const media::AudioAttributesInternal& attributes,
                                     int32_t* _aidl_return) override;
     binder::Status stopAudioSource(int32_t portId) override;
@@ -475,8 +475,8 @@
         Mutex mLock;
         ActivityManager mAm;
         bool mObserverRegistered = false;
-        std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids;
-        std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids;
+        std::unordered_map<uid_t, std::pair<bool, int>> mOverrideUids GUARDED_BY(mLock);
+        std::unordered_map<uid_t, std::pair<bool, int>> mCachedUids GUARDED_BY(mLock);
         std::vector<uid_t> mAssistantUids;
         std::vector<uid_t> mActiveAssistantUids;
         std::vector<uid_t> mA11yUids;
diff --git a/services/audiopolicy/service/Spatializer.h b/services/audiopolicy/service/Spatializer.h
index b101ae6..60030bd 100644
--- a/services/audiopolicy/service/Spatializer.h
+++ b/services/audiopolicy/service/Spatializer.h
@@ -23,6 +23,7 @@
 #include <android/media/SpatializationLevel.h>
 #include <android/media/SpatializationMode.h>
 #include <android/media/SpatializerHeadTrackingMode.h>
+#include <android/media/audio/common/AudioLatencyMode.h>
 #include <audio_utils/SimpleLog.h>
 #include <math.h>
 #include <media/AudioEffect.h>
@@ -168,8 +169,9 @@
 
     static std::string toString(audio_latency_mode_t mode) {
         // We convert to the AIDL type to print (eventually the legacy type will be removed).
-        const auto result = legacy2aidl_audio_latency_mode_t_LatencyMode(mode);
-        return result.has_value() ? media::toString(*result) : "unknown_latency_mode";
+        const auto result = legacy2aidl_audio_latency_mode_t_AudioLatencyMode(mode);
+        return result.has_value() ?
+                media::audio::common::toString(*result) : "unknown_latency_mode";
     }
 
     // If the Spatializer is not created, we send the status for metrics purposes.
diff --git a/services/audiopolicy/tests/Android.bp b/services/audiopolicy/tests/Android.bp
index 2e220bc..6813587 100644
--- a/services/audiopolicy/tests/Android.bp
+++ b/services/audiopolicy/tests/Android.bp
@@ -10,6 +10,10 @@
 cc_test {
     name: "audiopolicy_tests",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_static",
+    ],
+
     include_dirs: [
         "frameworks/av/services/audiopolicy",
     ],
@@ -30,6 +34,7 @@
     ],
 
     static_libs: [
+        "audioclient-types-aidl-cpp",
         "libaudiopolicycomponents",
         "libgmock",
     ],
@@ -56,6 +61,11 @@
 
 cc_test {
     name: "audio_health_tests",
+
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     require_root: true,
 
     shared_libs: [
@@ -65,7 +75,6 @@
         "liblog",
         "libmedia_helper",
         "libutils",
-        "android.media.audio.common.types-V1-cpp",
         "libaudioclient_aidl_conversion",
         "libstagefright_foundation",
         "libshmemcompat",
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index 057fa58..96f58d2 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -103,8 +103,12 @@
         ++mAudioPortListUpdateCount;
     }
 
-    status_t setDeviceConnectedState(
-            const struct audio_port_v7 *port __unused, bool connected __unused) override {
+    status_t setDeviceConnectedState(const struct audio_port_v7 *port, bool connected) override {
+        if (connected) {
+            mConnectedDevicePorts.push_back(*port);
+        } else {
+            mDisconnectedDevicePorts.push_back(*port);
+        }
         return NO_ERROR;
     }
 
@@ -150,6 +154,30 @@
         return NO_ERROR;
     }
 
+    size_t getConnectedDevicePortCount() const {
+        return mConnectedDevicePorts.size();
+    }
+
+    const struct audio_port_v7 *getLastConnectedDevicePort() const {
+        if (mConnectedDevicePorts.empty()) {
+            return nullptr;
+        }
+        auto it = --mConnectedDevicePorts.end();
+        return &(*it);
+    }
+
+    size_t getDisconnectedDevicePortCount() const {
+        return mDisconnectedDevicePorts.size();
+    }
+
+    const struct audio_port_v7 *getLastDisconnectedDevicePort() const {
+        if (mDisconnectedDevicePorts.empty()) {
+            return nullptr;
+        }
+        auto it = --mDisconnectedDevicePorts.end();
+        return &(*it);
+    }
+
 private:
     audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
     audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
@@ -158,6 +186,8 @@
     std::set<std::string> mAllowedModuleNames;
     size_t mAudioPortListUpdateCount = 0;
     size_t mRoutingUpdatedUpdateCount = 0;
+    std::vector<struct audio_port_v7> mConnectedDevicePorts;
+    std::vector<struct audio_port_v7> mDisconnectedDevicePorts;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 7441f20..2a7a060 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -37,6 +37,7 @@
     using AudioPolicyManager::getDirectProfilesForAttributes;
     using AudioPolicyManager::setDeviceConnectionState;
     using AudioPolicyManager::deviceToAudioPort;
+    using AudioPolicyManager::handleDeviceConfigChange;
     uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
 };
 
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index 10f8dc0..798332c 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -111,7 +111,7 @@
             continue;
         }
         std::string address = "11:22:33:44:55:66";
-        media::AudioPort aidlPort;
+        media::AudioPortFw aidlPort;
         ASSERT_EQ(OK, manager.deviceToAudioPort(device->type(), address.c_str(), "" /*name*/,
                                                  &aidlPort));
         ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 43b1a2a..1c40cfd 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -42,6 +42,32 @@
 using testing::UnorderedElementsAre;
 using android::content::AttributionSourceState;
 
+namespace {
+
+AudioMixMatchCriterion createUidCriterion(uint32_t uid, bool exclude = false) {
+    AudioMixMatchCriterion criterion;
+    criterion.mValue.mUid = uid;
+    criterion.mRule = exclude ? RULE_EXCLUDE_UID : RULE_MATCH_UID;
+    return criterion;
+}
+
+AudioMixMatchCriterion createUsageCriterion(audio_usage_t usage, bool exclude = false) {
+    AudioMixMatchCriterion criterion;
+    criterion.mValue.mUsage = usage;
+    criterion.mRule = exclude ? RULE_EXCLUDE_ATTRIBUTE_USAGE : RULE_MATCH_ATTRIBUTE_USAGE;
+    return criterion;
+}
+
+AudioMixMatchCriterion createCapturePresetCriterion(audio_source_t source, bool exclude = false) {
+    AudioMixMatchCriterion criterion;
+    criterion.mValue.mSource = source;
+    criterion.mRule = exclude ?
+        RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET : RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET;
+    return criterion;
+}
+
+} // namespace
+
 TEST(AudioPolicyManagerTestInit, EngineFailure) {
     AudioPolicyTestClient client;
     AudioPolicyTestManager manager(&client);
@@ -420,7 +446,7 @@
     sp<AudioProfile> ac3OutputProfile = new AudioProfile(
             AUDIO_FORMAT_AC3, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
     sp<AudioProfile> iec958OutputProfile = new AudioProfile(
-            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
+            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
     mMsdOutputDevice->addAudioProfile(pcmOutputProfile);
     mMsdOutputDevice->addAudioProfile(ac3OutputProfile);
     mMsdOutputDevice->addAudioProfile(iec958OutputProfile);
@@ -493,7 +519,7 @@
     // Add HDMI input device with IEC60958 profile for HDMI in -> MSD patching.
     mHdmiInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_HDMI);
     sp<AudioProfile> iec958InputProfile = new AudioProfile(
-            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate);
+            AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
     mHdmiInputDevice->addAudioProfile(iec958InputProfile);
     config.addDevice(mHdmiInputDevice);
     sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
@@ -651,8 +677,8 @@
     ASSERT_EQ(AUDIO_PORT_ROLE_SINK, patch->mPatch.sinks[0].role);
     ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sources[0].format);
     ASSERT_EQ(AUDIO_FORMAT_IEC60958, patch->mPatch.sinks[0].format);
-    ASSERT_EQ(AUDIO_CHANNEL_IN_STEREO, patch->mPatch.sources[0].channel_mask);
-    ASSERT_EQ(AUDIO_CHANNEL_OUT_STEREO, patch->mPatch.sinks[0].channel_mask);
+    ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sources[0].channel_mask);
+    ASSERT_EQ(AUDIO_CHANNEL_INDEX_MASK_24, patch->mPatch.sinks[0].channel_mask);
     ASSERT_EQ(k48000SamplingRate, patch->mPatch.sources[0].sample_rate);
     ASSERT_EQ(k48000SamplingRate, patch->mPatch.sinks[0].sample_rate);
     ASSERT_EQ(1, patchCount.deltaFromSnapshot());
@@ -728,7 +754,7 @@
     audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER;
     msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
     msdDirectConfig2.sample_rate = 48000;
-    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
 
     audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER;
     msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -795,7 +821,7 @@
     audio_config_t msdDirectConfig2 = AUDIO_CONFIG_INITIALIZER;
     msdDirectConfig2.format = AUDIO_FORMAT_IEC60958;
     msdDirectConfig2.sample_rate = 48000;
-    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    msdDirectConfig2.channel_mask = AUDIO_CHANNEL_INDEX_MASK_24;
 
     audio_config_t msdNonDirectConfig = AUDIO_CONFIG_INITIALIZER;
     msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT;
@@ -919,7 +945,29 @@
     EXPECT_TRUE(foundVoipTx);
 }
 
-using PolicyMixTuple = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, HandleDeviceConfigChange) {
+    {
+        const auto prevCounter = mClient->getRoutingUpdatedCounter();
+
+        EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                                                               AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+                                                               "", "", AUDIO_FORMAT_LDAC));
+        const auto currCounter = mClient->getRoutingUpdatedCounter();
+        EXPECT_GT(currCounter, prevCounter);
+    }
+    {
+        const auto prevCounter = mClient->getRoutingUpdatedCounter();
+        // Update device configuration
+        EXPECT_EQ(NO_ERROR, mManager->handleDeviceConfigChange(AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
+                                                               "" /*address*/, "" /*name*/,
+                                                               AUDIO_FORMAT_AAC));
+
+        // As mClient marks isReconfigA2dpSupported to false, device state needs to be toggled for
+        // config changes to take effect
+        const auto currCounter = mClient->getRoutingUpdatedCounter();
+        EXPECT_GT(currCounter, prevCounter);
+    }
+}
 
 class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
 protected:
@@ -927,7 +975,7 @@
 
     status_t addPolicyMix(int mixType, int mixFlag, audio_devices_t deviceType,
             std::string mixAddress, const audio_config_t& audioConfig,
-            const std::vector<PolicyMixTuple>& rules);
+            const std::vector<AudioMixMatchCriterion>& matchCriteria);
     void clearPolicyMix();
 
     Vector<AudioMix> mAudioMixes;
@@ -941,15 +989,8 @@
 
 status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(int mixType, int mixFlag,
         audio_devices_t deviceType, std::string mixAddress, const audio_config_t& audioConfig,
-        const std::vector<PolicyMixTuple>& rules) {
-    Vector<AudioMixMatchCriterion> myMixMatchCriteria;
-
-    for(const auto &rule: rules) {
-        myMixMatchCriteria.add(AudioMixMatchCriterion(
-                std::get<0>(rule), std::get<1>(rule), std::get<2>(rule)));
-    }
-
-    AudioMix myAudioMix(myMixMatchCriteria, mixType, audioConfig, mixFlag,
+        const std::vector<AudioMixMatchCriterion>& matchCriteria = {}) {
+    AudioMix myAudioMix(matchCriteria, mixType, audioConfig, mixFlag,
             String8(mixAddress.c_str()), 0);
     myAudioMix.mDeviceType = deviceType;
     // Clear mAudioMix before add new one to make sure we don't add already exist mixes.
@@ -983,13 +1024,13 @@
 
     // Only capture of playback is allowed in LOOP_BACK &RENDER mode
     ret = addPolicyMix(MIX_TYPE_RECORDERS, MIX_ROUTE_FLAG_LOOP_BACK_AND_RENDER,
-            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
     ASSERT_EQ(INVALID_OPERATION, ret);
 
     // Fail due to the device is already connected.
     clearPolicyMix();
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
-            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
     ASSERT_EQ(INVALID_OPERATION, ret);
 
     // The first time to register policy mixes with valid parameter should succeed.
@@ -998,8 +1039,7 @@
     audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
     audioConfig.sample_rate = k48000SamplingRate;
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
-            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
-            std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig);
     ASSERT_EQ(NO_ERROR, ret);
     // Registering the same policy mixes should fail.
     ret = mManager->registerPolicyMixes(mAudioMixes);
@@ -1010,19 +1050,19 @@
     // This will need to be updated if earpiece is added in the test configuration file.
     clearPolicyMix();
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
-            AUDIO_DEVICE_OUT_EARPIECE, "", audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_EARPIECE, "", audioConfig);
     ASSERT_EQ(INVALID_OPERATION, ret);
 
     // Registration should fail due to output not found.
     clearPolicyMix();
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
-            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
     ASSERT_EQ(INVALID_OPERATION, ret);
 
     // The first time to register valid policy mixes should succeed.
     clearPolicyMix();
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
-            AUDIO_DEVICE_OUT_SPEAKER, "", audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_SPEAKER, "", audioConfig);
     ASSERT_EQ(NO_ERROR, ret);
     // Registering the same policy mixes should fail.
     ret = mManager->registerPolicyMixes(mAudioMixes);
@@ -1037,8 +1077,7 @@
     audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
     audioConfig.sample_rate = k48000SamplingRate;
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
-            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
-            std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig);
     ASSERT_EQ(NO_ERROR, ret);
 
     // After successfully registering policy mixes, it should be able to unregister.
@@ -1051,6 +1090,37 @@
     ASSERT_EQ(INVALID_OPERATION, ret);
 }
 
+TEST_F(AudioPolicyManagerTestDynamicPolicy, RegisterPolicyWithConsistentMixSucceeds) {
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+    audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = k48000SamplingRate;
+
+    std::vector<AudioMixMatchCriterion> mixMatchCriteria = {
+        createUidCriterion(/*uid=*/42),
+        createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+    status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+                                AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+                                mixMatchCriteria);
+    ASSERT_EQ(NO_ERROR, ret);
+}
+
+TEST_F(AudioPolicyManagerTestDynamicPolicy, RegisterPolicyWithInconsistentMixFails) {
+    audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+    audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+    audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+    audioConfig.sample_rate = k48000SamplingRate;
+
+    std::vector<AudioMixMatchCriterion> mixMatchCriteria = {
+        createUidCriterion(/*uid=*/42),
+        createUidCriterion(/*uid=*/1235, /*exclude=*/true),
+        createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/true)};
+    status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+                                AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig,
+                                mixMatchCriteria);
+    ASSERT_EQ(INVALID_OPERATION, ret);
+}
+
 class AudioPolicyManagerTestForHdmi
         : public AudioPolicyManagerTestWithConfigurationFile,
           public testing::WithParamInterface<audio_format_t> {
@@ -1275,7 +1345,7 @@
     audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
     audioConfig.sample_rate = k48000SamplingRate;
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
-            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_REMOTE_SUBMIX, "", audioConfig);
     ASSERT_EQ(INVALID_OPERATION, ret);
 
     ret = mManager->unregisterPolicyMixes(mAudioMixes);
@@ -1290,9 +1360,9 @@
 
     std::unique_ptr<RecordingActivityTracker> mTracker;
 
-    std::vector<PolicyMixTuple> mUsageRules = {
-            {AUDIO_USAGE_MEDIA, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE},
-            {AUDIO_USAGE_ALARM, AUDIO_SOURCE_DEFAULT, RULE_MATCH_ATTRIBUTE_USAGE}
+    std::vector<AudioMixMatchCriterion> mUsageRules = {
+            createUsageCriterion(AUDIO_USAGE_MEDIA),
+            createUsageCriterion(AUDIO_USAGE_ALARM)
     };
 
     struct audio_port_v7 mInjectionPort;
@@ -1352,9 +1422,10 @@
     getOutputForAttr(&playbackRoutedPortId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
             k48000SamplingRate, AUDIO_OUTPUT_FLAG_NONE, nullptr /*output*/, nullptr /*portId*/,
             attr);
-    if (std::find_if(begin(mUsageRules), end(mUsageRules), [&usage](const auto &usageRule) {
-            return (std::get<0>(usageRule) == usage) &&
-            (std::get<2>(usageRule) == RULE_MATCH_ATTRIBUTE_USAGE);}) != end(mUsageRules) ||
+    if (std::find_if(begin(mUsageRules), end(mUsageRules),
+                [&usage](const AudioMixMatchCriterion &c) {
+                              return c.mRule == RULE_MATCH_ATTRIBUTE_USAGE &&
+                                     c.mValue.mUsage == usage;}) != end(mUsageRules) ||
             (strncmp(attr.tags, "addr=", strlen("addr=")) == 0 &&
                     strncmp(attr.tags + strlen("addr="), mMixAddress.c_str(),
                     AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - strlen("addr=") - 1) == 0)) {
@@ -1475,10 +1546,10 @@
 
     std::unique_ptr<RecordingActivityTracker> mTracker;
 
-    std::vector<PolicyMixTuple> mSourceRules = {
-        {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_CAMCORDER, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
-        {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_MIC, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET},
-        {AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_VOICE_COMMUNICATION, RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET}
+    std::vector<AudioMixMatchCriterion> mSourceRules = {
+        createCapturePresetCriterion(AUDIO_SOURCE_CAMCORDER),
+        createCapturePresetCriterion(AUDIO_SOURCE_MIC),
+        createCapturePresetCriterion(AUDIO_SOURCE_VOICE_COMMUNICATION)
     };
 
     struct audio_port_v7 mExtractionPort;
@@ -1538,9 +1609,10 @@
     audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
     getInputForAttr(attr, mTracker->getRiid(), &captureRoutedPortId, AUDIO_FORMAT_PCM_16_BIT,
             AUDIO_CHANNEL_IN_STEREO, k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &portId);
-    if (std::find_if(begin(mSourceRules), end(mSourceRules), [&source](const auto &sourceRule) {
-            return (std::get<1>(sourceRule) == source) &&
-            (std::get<2>(sourceRule) == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET);})
+    if (std::find_if(begin(mSourceRules), end(mSourceRules),
+               [&source](const AudioMixMatchCriterion &c) {
+            return c.mRule == RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET &&
+                   c.mValue.mSource == source;})
             != end(mSourceRules)) {
         EXPECT_EQ(mExtractionPort.id, captureRoutedPortId);
     } else {
@@ -1700,6 +1772,45 @@
             address.c_str(), name.c_str(), AUDIO_FORMAT_DEFAULT));
 }
 
+android::media::audio::common::ExtraAudioDescriptor make_ExtraAudioDescriptor(
+        android::media::audio::common::AudioStandard audioStandard,
+        android::media::audio::common::AudioEncapsulationType audioEncapsulationType) {
+    android::media::audio::common::ExtraAudioDescriptor result;
+    result.standard = audioStandard;
+    result.audioDescriptor = {0xb4, 0xaf, 0x98, 0x1a};
+    result.encapsulationType = audioEncapsulationType;
+    return result;
+}
+
+TEST_P(AudioPolicyManagerTestDeviceConnection, PassingExtraAudioDescriptors) {
+    const audio_devices_t type = std::get<0>(GetParam());
+    if (!audio_device_is_digital(type)) {
+        // EADs are used only for HDMI devices.
+        GTEST_SKIP() << "Not a digital device type: " << audio_device_to_string(type);
+    }
+    const std::string name = std::get<1>(GetParam());
+    const std::string address = std::get<2>(GetParam());
+    android::media::AudioPortFw audioPort;
+    ASSERT_EQ(NO_ERROR,
+            mManager->deviceToAudioPort(type, address.c_str(), name.c_str(), &audioPort));
+    android::media::audio::common::AudioPort& port = audioPort.hal;
+    port.extraAudioDescriptors.push_back(make_ExtraAudioDescriptor(
+                    android::media::audio::common::AudioStandard::EDID,
+                    android::media::audio::common::AudioEncapsulationType::IEC61937));
+    const size_t lastConnectedDevicePortCount = mClient->getConnectedDevicePortCount();
+    const size_t lastDisconnectedDevicePortCount = mClient->getDisconnectedDevicePortCount();
+    EXPECT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+                    AUDIO_POLICY_DEVICE_STATE_AVAILABLE, port, AUDIO_FORMAT_DEFAULT));
+    EXPECT_EQ(lastConnectedDevicePortCount + 1, mClient->getConnectedDevicePortCount());
+    EXPECT_EQ(lastDisconnectedDevicePortCount, mClient->getDisconnectedDevicePortCount());
+    const audio_port_v7* devicePort = mClient->getLastConnectedDevicePort();
+    EXPECT_EQ(port.extraAudioDescriptors.size(), devicePort->num_extra_audio_descriptors);
+    EXPECT_EQ(AUDIO_STANDARD_EDID, devicePort->extra_audio_descriptors[0].standard);
+    EXPECT_EQ(AUDIO_ENCAPSULATION_TYPE_IEC61937,
+            devicePort->extra_audio_descriptors[0].encapsulation_type);
+    EXPECT_NE(0, devicePort->extra_audio_descriptors[0].descriptor[0]);
+}
+
 INSTANTIATE_TEST_CASE_P(
         DeviceConnectionState,
         AudioPolicyManagerTestDeviceConnection,
@@ -1738,7 +1849,7 @@
     audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
     const std::string kTestBusMediaOutput = "bus0_media_out";
     ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
-            AUDIO_DEVICE_OUT_BUS, kTestBusMediaOutput, audioConfig, std::vector<PolicyMixTuple>());
+            AUDIO_DEVICE_OUT_BUS, kTestBusMediaOutput, audioConfig);
     ASSERT_EQ(NO_ERROR, ret);
 
     audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 5e1822a..d342aea 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -71,6 +71,9 @@
                 <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"
                             role="source" address="hfp_client_in">
                 </devicePort>
+                <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink"
+                            encodedFormats="AUDIO_FORMAT_LDAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_AAC AUDIO_FORMAT_SBC">
+                </devicePort>
             </devicePorts>
             <routes>
                 <route type="mix" sink="Speaker"
@@ -85,6 +88,8 @@
                        sources="mixport_bt_hfp_output,voip_rx"/>
                 <route type="mix" sink="mixport_bt_hfp_input"
                        sources="BT SCO Headset Mic"/>
+                <route type="mix" sink="BT A2DP Out"
+                       sources="primary output"/>
             </routes>
         </module>
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index d87b630..a7c9bac 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -4023,7 +4023,7 @@
     int toggleType __unused, int sensor __unused, bool enabled) {
     {
         Mutex::Autolock _l(mSensorPrivacyLock);
-        mSensorPrivacyEnabled = mSpm.isToggleSensorPrivacyEnabled(SensorPrivacyManager::TOGGLE_SENSOR_CAMERA);
+        mSensorPrivacyEnabled = enabled;
     }
     // if sensor privacy is enabled then block all clients from accessing the camera
     if (enabled) {
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 123cd75..8b2af90 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -953,6 +953,12 @@
                 false);
 
     if (availableVideoStabilizationModes.count > 1) {
+        for (size_t i = 0; i < availableVideoStabilizationModes.count; i++) {
+            if (availableVideoStabilizationModes.data.u8[i] ==
+                ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON) {
+                videoStabilizationOnSupported = true;
+            }
+        }
         params.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
                 CameraParameters::TRUE);
     } else {
@@ -2373,9 +2379,11 @@
             reqCropRegion, 4);
     if (res != OK) return res;
 
-    uint8_t reqVstabMode = videoStabilization ?
+    uint8_t reqVstabMode = videoStabilization ? videoStabilizationOnSupported ?
             ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON :
+                    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION :
             ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF;
+
     res = request->update(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
             &reqVstabMode, 1);
     if (res != OK) return res;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index cbe62a7..fd18a5d 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -147,6 +147,7 @@
 
     bool recordingHint;
     bool videoStabilization;
+    bool videoStabilizationOnSupported = false;
 
     CameraParameters2 params;
     String8 paramsFlattened;
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1f86414..dd23c2e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -947,8 +947,8 @@
     std::vector<int> surfaceIds;
     bool isDepthCompositeStream =
             camera3::DepthCompositeStream::isDepthCompositeStream(surfaces[0]);
-    bool isHeicCompisiteStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
-    if (isDepthCompositeStream || isHeicCompisiteStream) {
+    bool isHeicCompositeStream = camera3::HeicCompositeStream::isHeicCompositeStream(surfaces[0]);
+    if (isDepthCompositeStream || isHeicCompositeStream) {
         sp<CompositeStream> compositeStream;
         if (isDepthCompositeStream) {
             compositeStream = new camera3::DepthCompositeStream(mDevice, getRemoteCallback());
@@ -1863,6 +1863,10 @@
         mCompositeStreamMap.clear();
         mInputStream = {false, 0, 0, 0, 0};
     } else {
+        // In case we failed to register the offline client, ensure that it still initialized
+        // so that all failing requests can return back correctly once the object is released.
+        offlineClient->initialize(nullptr /*cameraProviderManager*/, String8()/*monitorTags*/);
+
         switch(ret) {
             case BAD_VALUE:
                 return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 0f31c66..52d0020 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -29,6 +29,11 @@
 status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
     ATRACE_CALL();
 
+    if (mFrameProcessor.get() != nullptr) {
+        // Already initialized
+        return OK;
+    }
+
     // Verify ops permissions
     auto res = startCameraOps();
     if (res != OK) {
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 237ce5e..2cc8e33 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -931,7 +931,7 @@
                 tempOutputFile.str().c_str(), errno);
         return NO_INIT;
     }
-    inputFrame.muxer = new MediaMuxer(inputFrame.fileFd, MediaMuxer::OUTPUT_FORMAT_HEIF);
+    inputFrame.muxer = MediaMuxer::create(inputFrame.fileFd, MediaMuxer::OUTPUT_FORMAT_HEIF);
     if (inputFrame.muxer == nullptr) {
         ALOGE("%s: Failed to create MediaMuxer for file fd %d",
                 __FUNCTION__, inputFrame.fileFd);
@@ -1601,7 +1601,7 @@
     return OK;
 }
 
-void HeicCompositeStream::initCopyRowFunction(int32_t width)
+void HeicCompositeStream::initCopyRowFunction([[maybe_unused]] int32_t width)
 {
     using namespace libyuv;
 
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 43f92a9..5ab7023 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -586,7 +586,11 @@
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
     mDeviceState = newState;
     status_t res = OK;
-    for (auto& provider : mProviders) {
+    // Make a copy of mProviders because we unlock mInterfaceMutex temporarily
+    // within the loop. It's possible that during the time mInterfaceMutex is
+    // unlocked, mProviders has changed.
+    auto providers = mProviders;
+    for (auto& provider : providers) {
         ALOGV("%s: Notifying %s for new state 0x%" PRIx64,
                 __FUNCTION__, provider->mProviderName.c_str(), newState);
         // b/199240726 Camera providers can for example try to add/remove
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index 67c4841..49bbd07 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -293,7 +293,7 @@
             if (link != STATUS_OK) {
                 ALOGW("%s: Unable to link to provider '%s' death notifications",
                         __FUNCTION__, mProviderName.c_str());
-                mManager->removeProvider(mProviderName);
+                mManager->removeProvider(mProviderInstance);
                 return nullptr;
             }
 
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 630090b..6be0cca 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -388,7 +388,7 @@
                   __FUNCTION__,
                   mProviderName.c_str(),
                   linked.description().c_str());
-              mManager->removeProvider(mProviderName);
+              mManager->removeProvider(mProviderInstance);
               return nullptr;
             } else if (!linked) {
               ALOGW("%s: Unable to link to provider '%s' death notifications",
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d033395..e631f8b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -258,20 +258,28 @@
             Mutex::Autolock l(mLock);
             if (mStatus == STATUS_UNINITIALIZED) return res;
 
-            if (mStatus == STATUS_ACTIVE ||
-                    (mStatus == STATUS_ERROR && mRequestThread != NULL)) {
-                res = mRequestThread->clearRepeatingRequests();
-                if (res != OK) {
-                    SET_ERR_L("Can't stop streaming");
-                    // Continue to close device even in case of error
-                } else {
-                    res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+            if (mRequestThread != NULL) {
+                if (mStatus == STATUS_ACTIVE || mStatus == STATUS_ERROR) {
+                    res = mRequestThread->clear();
                     if (res != OK) {
-                        SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
-                                maxExpectedDuration);
+                        SET_ERR_L("Can't stop streaming");
                         // Continue to close device even in case of error
+                    } else {
+                        res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration);
+                        if (res != OK) {
+                            SET_ERR_L("Timeout waiting for HAL to drain (% " PRIi64 " ns)",
+                                    maxExpectedDuration);
+                            // Continue to close device even in case of error
+                        }
                     }
                 }
+                // Signal to request thread that we're not expecting any
+                // more requests. This will be true since once we're in
+                // disconnect and we've cleared off the request queue, the
+                // request thread can't receive any new requests through
+                // binder calls - since disconnect holds
+                // mBinderSerialization lock.
+                mRequestThread->setRequestClearing();
             }
 
             if (mStatus == STATUS_ERROR) {
@@ -3060,7 +3068,8 @@
 
 }
 
-status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(/*out*/int64_t *lastFrameNumber) {
+status_t Camera3Device::RequestThread::clearRepeatingRequestsLocked(
+        /*out*/int64_t *lastFrameNumber) {
     std::vector<int32_t> streamIds;
     for (const auto& request : mRepeatingRequests) {
         for (const auto& stream : request->mOutputStreams) {
@@ -3085,8 +3094,6 @@
     Mutex::Autolock l(mRequestLock);
     ALOGV("RequestThread::%s:", __FUNCTION__);
 
-    mRepeatingRequests.clear();
-
     // Send errors for all requests pending in the request queue, including
     // pending repeating requests
     sp<NotificationListener> listener = mListener.promote();
@@ -3124,10 +3131,7 @@
 
     Mutex::Autolock al(mTriggerMutex);
     mTriggerMap.clear();
-    if (lastFrameNumber != NULL) {
-        *lastFrameNumber = mRepeatingLastFrameNumber;
-    }
-    mRepeatingLastFrameNumber = hardware::camera2::ICameraDeviceUser::NO_IN_FLIGHT_REPEATING_FRAMES;
+    clearRepeatingRequestsLocked(lastFrameNumber);
     mRequestClearing = true;
     mRequestSignal.signal();
     return OK;
@@ -4252,6 +4256,11 @@
     return;
 }
 
+void Camera3Device::RequestThread::setRequestClearing() {
+    Mutex::Autolock l(mRequestLock);
+    mRequestClearing = true;
+}
+
 sp<Camera3Device::CaptureRequest>
         Camera3Device::RequestThread::waitForNextRequestLocked() {
     status_t res;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index cd214f6..746205b 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -466,6 +466,28 @@
                 // Verify buffer caches
                 std::vector<uint64_t> bufIds(offlineStream.circulatingBufferIds.begin(),
                         offlineStream.circulatingBufferIds.end());
+                {
+                    // Due to timing it is possible that we may not have any remaining pending
+                    // capture requests that can update the caches on Hal side. This can result in
+                    // buffer cache mismatch between the service and the Hal and must be accounted
+                    // for.
+                    std::lock_guard<std::mutex> l(mFreedBuffersLock);
+                    for (const auto& it : mFreedBuffers) {
+                        if (it.first == id) {
+                            ALOGV("%s: stream ID %d buffer id %" PRIu64 " cache removal still "
+                                    "pending", __FUNCTION__, id, it.second);
+                            const auto& cachedEntry = std::find(bufIds.begin(), bufIds.end(),
+                                    it.second);
+                            if (cachedEntry != bufIds.end()) {
+                                bufIds.erase(cachedEntry);
+                            } else {
+                                ALOGE("%s: stream ID %d buffer id %" PRIu64 " cache removal still "
+                                        "pending however buffer is no longer in the offline stream "
+                                        "info!", __FUNCTION__, id, it.second);
+                            }
+                        }
+                    }
+                }
                 if (!verifyBufferIds(id, bufIds)) {
                     ALOGE("%s: stream ID %d buffer cache records mismatch!", __FUNCTION__, id);
                     return UNKNOWN_ERROR;
@@ -848,6 +870,9 @@
          */
         void     setPaused(bool paused);
 
+        // set mRequestClearing - no new requests are expected to be queued to RequestThread
+        void setRequestClearing();
+
         /**
          * Wait until thread processes the capture request with settings'
          * android.request.id == requestId.
@@ -1002,7 +1027,7 @@
 
         wp<NotificationListener> mListener;
 
-        const String8&     mId;       // The camera ID
+        const String8      mId;       // The camera ID
         int                mStatusId; // The RequestThread's component ID for
                                       // status tracking
 
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index 7cfa255..1e7bd57 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -81,7 +81,6 @@
 Camera3OfflineSession::~Camera3OfflineSession() {
     ATRACE_CALL();
     ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
-    disconnectImpl();
 }
 
 const String8& Camera3OfflineSession::getId() const {
@@ -96,7 +95,6 @@
 
 status_t Camera3OfflineSession::disconnect() {
     ATRACE_CALL();
-    disconnectSession();
     return disconnectImpl();
 }
 
@@ -132,6 +130,8 @@
         streams.push_back(mInputStream);
     }
 
+    closeSessionLocked();
+
     FlushInflightReqStates states {
         mId, mOfflineReqsLock, mOfflineReqs, mUseHalBufManager,
         listener, *this, mBufferRecords, *this, mSessionStatsBuilder};
@@ -140,6 +140,7 @@
 
     {
         std::lock_guard<std::mutex> lock(mLock);
+        releaseSessionLocked();
         mOutputStreams.clear();
         mInputStream.clear();
         mStatus = STATUS_CLOSED;
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index 5ee6ca5..e780043 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -274,7 +274,12 @@
     void setErrorStateLockedV(const char *fmt, va_list args);
 
     status_t disconnectImpl();
-    virtual void disconnectSession() = 0;
+
+    // Clients need to ensure that 'mInterfaceLock' is acquired before calling this method
+    virtual void closeSessionLocked() = 0;
+
+    // Clients need to ensure that 'mLock' is acquired before calling this method
+    virtual void releaseSessionLocked() = 0;
 
 }; // class Camera3OfflineSession
 
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
index 4b1fb1d..3c3db97 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
@@ -48,7 +48,7 @@
 AidlCamera3OfflineSession::~AidlCamera3OfflineSession() {
     ATRACE_CALL();
     ALOGV("%s: Tearing down aidl offline session for camera id %s", __FUNCTION__, mId.string());
-    AidlCamera3OfflineSession::disconnectSession();
+    Camera3OfflineSession::disconnectImpl();
 }
 
 status_t AidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
@@ -247,12 +247,17 @@
     return ::ndk::ScopedAStatus::ok();
 }
 
-void AidlCamera3OfflineSession::disconnectSession() {
-  std::lock_guard<std::mutex> lock(mLock);
-  if (mSession != nullptr) {
-      mSession->close();
-  }
-  mSession.reset();
+void AidlCamera3OfflineSession::closeSessionLocked() {
+    if (mSession != nullptr) {
+        auto err = mSession->close();
+        if (!err.isOk()) {
+            ALOGE("%s: Close transaction error: %s", __FUNCTION__, err.getDescription().c_str());
+        }
+    }
+}
+
+void AidlCamera3OfflineSession::releaseSessionLocked() {
+    mSession.reset();
 }
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
index d107af6..b31ffb7 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
@@ -131,7 +131,9 @@
 
     std::shared_ptr<AidlCameraDeviceCallbacks> mCallbacks;
 
-    virtual void disconnectSession() override;
+    virtual void closeSessionLocked() override;
+
+    virtual void releaseSessionLocked() override;
 
 }; // class AidlCamera3OfflineSession
 
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 2bd4660..72343bc 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -82,9 +82,6 @@
             const hardware::hidl_vec<
                     hardware::camera::device::V3_2::StreamBuffer>& buffers) override;
 
-    // Handle one notify message
-    void notify(const hardware::camera::device::V3_2::NotifyMsg& msg);
-
     status_t switchToOffline(const std::vector<int32_t>& streamsToKeep,
             /*out*/ sp<CameraOfflineSessionBase>* session) override;
 
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
index 0a6a6f7..28b2b47 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -39,7 +39,7 @@
 HidlCamera3OfflineSession::~HidlCamera3OfflineSession() {
     ATRACE_CALL();
     ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string());
-    HidlCamera3OfflineSession::disconnectSession();
+    Camera3OfflineSession::disconnectImpl();
 }
 
 status_t HidlCamera3OfflineSession::initialize(wp<NotificationListener> listener) {
@@ -229,13 +229,17 @@
     return hardware::Void();
 }
 
-void HidlCamera3OfflineSession::disconnectSession() {
-  // TODO: Make sure this locking is correct.
-  std::lock_guard<std::mutex> lock(mLock);
-  if (mSession != nullptr) {
-      mSession->close();
-  }
-  mSession.clear();
+void HidlCamera3OfflineSession::closeSessionLocked() {
+    if (mSession != nullptr) {
+        auto err = mSession->close();
+        if (!err.isOk()) {
+            ALOGE("%s: Close transaction error: %s", __FUNCTION__, err.description().c_str());
+        }
+    }
+}
+
+void HidlCamera3OfflineSession::releaseSessionLocked() {
+    mSession.clear();
 }
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
index 597cc5d..d22a447 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
@@ -101,7 +101,9 @@
     // FMQ to write result on. Must be guarded by mProcessCaptureResultLock.
     std::unique_ptr<ResultMetadataQueue> mResultMetadataQueue;
 
-    virtual void disconnectSession() override;
+    virtual void closeSessionLocked() override;
+
+    virtual void releaseSessionLocked() override;
 }; // class Camera3OfflineSession
 
 }; // namespace android
diff --git a/services/mediacodec/Android.bp b/services/mediacodec/Android.bp
index 4488efb..a2f17c2 100644
--- a/services/mediacodec/Android.bp
+++ b/services/mediacodec/Android.bp
@@ -54,6 +54,9 @@
         arm64: {
             src: "seccomp_policy/mediaswcodec-arm64.policy",
         },
+        riscv64: {
+            src: "seccomp_policy/mediaswcodec-riscv64.policy",
+        },
         x86: {
             src: "seccomp_policy/mediaswcodec-x86.policy",
         },
@@ -144,6 +147,9 @@
         arm64: {
             src: "seccomp_policy/mediacodec-arm64.policy",
         },
+        riscv64: {
+            enabled: false,
+        },
         x86: {
             src: "seccomp_policy/mediacodec-x86.policy",
         },
diff --git a/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy b/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
new file mode 100644
index 0000000..a55c3eb
--- /dev/null
+++ b/services/mediacodec/seccomp_policy/mediaswcodec-riscv64.policy
@@ -0,0 +1,60 @@
+# 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.
+
+read: 1
+mprotect: 1
+prctl: 1
+openat: 1
+getuid: 1
+getrlimit: 1
+writev: 1
+ioctl: 1
+close: 1
+mmap: 1
+munmap: 1
+fstat: 1
+madvise: 1
+newfstatat: 1
+futex: 1
+faccessat: 1
+lseek: 1
+clone: 1
+sigaltstack: 1
+rt_sigprocmask: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+readlinkat: 1
+fstatfs: 1
+pread64: 1
+mremap: 1
+dup: 1
+set_tid_address: 1
+write: 1
+nanosleep: 1
+sched_setscheduler: 1
+uname: 1
+memfd_create: 1
+ftruncate: 1
+getdents64: 1
+ppoll: 1
+
+# Required by AddressSanitizer
+gettid: 1
+sched_yield: 1
+getpid: 1
+
+@include /apex/com.android.media.swcodec/etc/seccomp_policy/code_coverage.riscv64.policy
diff --git a/services/mediaextractor/Android.bp b/services/mediaextractor/Android.bp
index 85ce110..acafe56 100644
--- a/services/mediaextractor/Android.bp
+++ b/services/mediaextractor/Android.bp
@@ -74,6 +74,9 @@
         arm64: {
             src: "seccomp_policy/mediaextractor-arm64.policy",
         },
+        riscv64: {
+            src: "seccomp_policy/mediaextractor-riscv64.policy",
+        },
         x86: {
             src: "seccomp_policy/mediaextractor-x86.policy",
         },
diff --git a/services/mediaextractor/seccomp_policy/mediaextractor-riscv64.policy b/services/mediaextractor/seccomp_policy/mediaextractor-riscv64.policy
new file mode 100644
index 0000000..df143dd
--- /dev/null
+++ b/services/mediaextractor/seccomp_policy/mediaextractor-riscv64.policy
@@ -0,0 +1,48 @@
+# Organized by frequency of systemcall - in descending order for
+# best performance.
+ioctl: 1
+futex: 1
+prctl: 1
+write: 1
+getpriority: 1
+close: 1
+dup: 1
+mmap: 1
+munmap: 1
+openat: 1
+mprotect: 1
+madvise: 1
+getuid: 1
+fstat: 1
+fstatfs: 1
+read: 1
+setpriority: 1
+sigaltstack: 1
+clone: 1
+sched_setscheduler: 1
+lseek: 1
+newfstatat: 1
+faccessat: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+rt_sigprocmask: 1
+getrlimit: 1
+nanosleep: 1
+getrandom: 1
+timer_create: 1
+timer_settime: 1
+timer_delete: 1
+
+# for dynamically loading extractors
+getdents64: 1
+readlinkat: 1
+pread64: 1
+mremap: 1
+
+# Required by Sanitizers
+sched_yield: 1
+
+@include /apex/com.android.media/etc/seccomp_policy/crash_dump.riscv64.policy
+@include /apex/com.android.media/etc/seccomp_policy/code_coverage.riscv64.policy
diff --git a/services/mediametrics/Android.bp b/services/mediametrics/Android.bp
index 11534bb..c90488f 100644
--- a/services/mediametrics/Android.bp
+++ b/services/mediametrics/Android.bp
@@ -138,6 +138,7 @@
         "AudioTypes.cpp",
         "cleaner.cpp",
         "iface_statsd.cpp",
+        "MediaDrmStatsdHelper.cpp",
         "MediaMetricsService.cpp",
         "statsd_audiopolicy.cpp",
         "statsd_audiorecord.cpp",
@@ -169,7 +170,7 @@
         "libmemunreachable",
         "libprotobuf-cpp-lite",
         "libstagefright_foundation",
-        "libstatslog",
+        "libstats_media_metrics",
         "libstatspull",
         "libstatssocket",
         "libutils",
@@ -177,6 +178,7 @@
     ],
 
     export_shared_lib_headers: [
+        "libstats_media_metrics",
         "libstatspull",
         "libstatssocket",
     ],
@@ -200,3 +202,33 @@
         "libaudioutils_headers",
     ],
 }
+
+cc_library {
+    name: "libstats_media_metrics",
+    generated_sources: ["stats_media_metrics.cpp"],
+    generated_headers: ["stats_media_metrics.h"],
+    export_generated_headers: ["stats_media_metrics.h"],
+    shared_libs: [
+        "libcutils",
+        "libstatspull",
+        "libstatssocket",
+    ],
+}
+
+genrule {
+    name: "stats_media_metrics.h",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --header $(genDir)/stats_media_metrics.h --module media_metrics --namespace android,stats,media_metrics",
+    out: [
+        "stats_media_metrics.h",
+    ],
+}
+
+genrule {
+    name: "stats_media_metrics.cpp",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --cpp $(genDir)/stats_media_metrics.cpp --module media_metrics --namespace android,stats,media_metrics --importHeader stats_media_metrics.h",
+    out: [
+        "stats_media_metrics.cpp",
+    ],
+}
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index b03e418..119bb6c 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -24,7 +24,7 @@
 #include <aaudio/AAudio.h>        // error codes
 #include <audio_utils/clock.h>    // clock conversions
 #include <cutils/properties.h>
-#include <statslog.h>             // statsd
+#include <stats_media_metrics.h>             // statsd
 #include <system/audio.h>
 
 #include "AudioTypes.h"           // string to int conversions
@@ -292,7 +292,7 @@
     int result = 0;
 
 #ifdef STATSD_ENABLE
-    result = android::util::stats_write(args...);
+    result = stats::media_metrics::stats_write(args...);
 #endif
     return result;
 }
@@ -308,7 +308,7 @@
     std::stringstream ss;
 
 #ifdef STATSD_ENABLE
-    result = android::util::stats_write(args...);
+    result = stats::media_metrics::stats_write(args...);
     ss << "result:" << result;
 #endif
     ss << " { ";
@@ -607,7 +607,7 @@
         const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
 
         // currently we only send create status events.
-        const int32_t event = android::util::
+        const int32_t event = stats::media_metrics::
                 MEDIAMETRICS_AUDIO_RECORD_STATUS_REPORTED__EVENT__AUDIO_RECORD_EVENT_CREATE;
 
         // The following fields should all be present in a create event.
@@ -647,7 +647,7 @@
                 __func__, AMEDIAMETRICS_KEY_PREFIX_AUDIO_RECORD, AMEDIAMETRICS_PROP_SAMPLERATE);
 
         const auto [ result, str ] = sendToStatsd(AudioRecordStatusFields,
-                CONDITION(android::util::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED)
                 , atom_status
                 , message.c_str()
                 , subCode
@@ -661,7 +661,7 @@
                 , sampleRate
                 );
         ALOGV("%s: statsd %s", __func__, str.c_str());
-        mStatsdLog->log(android::util::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED, str);
+        mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIORECORDSTATUS_REPORTED, str);
         return true;
     }
     return false;
@@ -679,7 +679,7 @@
         const int atom_status = types::lookup<types::STATUS, int32_t>(statusString);
 
         // currently we only send create status events.
-        const int32_t event = android::util::
+        const int32_t event = stats::media_metrics::
                 MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__EVENT__AUDIO_TRACK_EVENT_CREATE;
 
         // The following fields should all be present in a create event.
@@ -734,7 +734,7 @@
                 __func__,
                 AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK, AMEDIAMETRICS_PROP_PLAYBACK_PITCH);
         const auto [ result, str ] = sendToStatsd(AudioTrackStatusFields,
-                CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED)
                 , atom_status
                 , message.c_str()
                 , subCode
@@ -751,7 +751,7 @@
                 , (float)pitch
                 );
         ALOGV("%s: statsd %s", __func__, str.c_str());
-        mStatsdLog->log(android::util::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
+        mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKSTATUS_REPORTED, str);
         return true;
     }
     return false;
@@ -860,7 +860,7 @@
         if (clientCalled  // only log if client app called AudioRecord.
                 && mAudioAnalytics.mDeliverStatistics) {
             const auto [ result, str ] = sendToStatsd(AudioRecordDeviceUsageFields,
-                    CONDITION(android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
+                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED)
                     , ENUM_EXTRACT(inputDeviceStatsd)
                     , inputDeviceNames.c_str()
                     , deviceTimeNs
@@ -878,7 +878,7 @@
                     );
             ALOGV("%s: statsd %s", __func__, str.c_str());
             mAudioAnalytics.mStatsdLog->log(
-                    android::util::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
+                    stats::media_metrics::MEDIAMETRICS_AUDIORECORDDEVICEUSAGE_REPORTED, str);
         }
     } break;
     case THREAD: {
@@ -930,7 +930,7 @@
               << ")";
         if (mAudioAnalytics.mDeliverStatistics) {
             const auto [ result, str ] = sendToStatsd(AudioThreadDeviceUsageFields,
-                CONDITION(android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED)
                 , ENUM_EXTRACT(deviceStatsd)
                 , deviceNames.c_str()
                 , deviceTimeNs
@@ -944,7 +944,7 @@
             );
             ALOGV("%s: statsd %s", __func__, str.c_str());
             mAudioAnalytics.mStatsdLog->log(
-                    android::util::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
+                    stats::media_metrics::MEDIAMETRICS_AUDIOTHREADDEVICEUSAGE_REPORTED, str);
         }
     } break;
     case TRACK: {
@@ -1050,7 +1050,7 @@
         if (clientCalled // only log if client app called AudioTracks
                 && mAudioAnalytics.mDeliverStatistics) {
             const auto [ result, str ] = sendToStatsd(AudioTrackDeviceUsageFields,
-                    CONDITION(android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
+                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED)
                     , ENUM_EXTRACT(outputDeviceStatsd)
                     , outputDeviceNames.c_str()
                     , deviceTimeNs
@@ -1074,7 +1074,7 @@
                     );
             ALOGV("%s: statsd %s", __func__, str.c_str());
             mAudioAnalytics.mStatsdLog->log(
-                    android::util::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
+                    stats::media_metrics::MEDIAMETRICS_AUDIOTRACKDEVICEUSAGE_REPORTED, str);
         }
         } break;
     }
@@ -1136,7 +1136,7 @@
             const long_enum_type_t inputDeviceBits{};
 
             const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
-                    CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
                     , ENUM_EXTRACT(inputDeviceBits)
                     , ENUM_EXTRACT(outputDeviceBits)
                     , mA2dpDeviceName.c_str()
@@ -1146,7 +1146,7 @@
                     );
             ALOGV("%s: statsd %s", __func__, str.c_str());
             mAudioAnalytics.mStatsdLog->log(
-                    android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
+                    stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
         }
     }
 }
@@ -1190,7 +1190,7 @@
                 << " deviceName:" << mA2dpDeviceName;
         if (mAudioAnalytics.mDeliverStatistics) {
             const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
-                    CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+                    CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
                     , ENUM_EXTRACT(inputDeviceBits)
                     , ENUM_EXTRACT(outputDeviceBits)
                     , mA2dpDeviceName.c_str()
@@ -1200,7 +1200,7 @@
                     );
             ALOGV("%s: statsd %s", __func__, str.c_str());
             mAudioAnalytics.mStatsdLog->log(
-                    android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
+                    stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
         }
         return;
     }
@@ -1217,7 +1217,7 @@
             << " deviceName:" << mA2dpDeviceName;
     if (mAudioAnalytics.mDeliverStatistics) {
         const auto [ result, str ] = sendToStatsd(AudioDeviceConnectionFields,
-                CONDITION(android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED)
                 , ENUM_EXTRACT(inputDeviceBits)
                 , ENUM_EXTRACT(outputDeviceBits)
                 , mA2dpDeviceName.c_str()
@@ -1227,7 +1227,7 @@
                 );
         ALOGV("%s: statsd %s", __func__, str.c_str());
         mAudioAnalytics.mStatsdLog->log(
-                android::util::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
+                stats::media_metrics::MEDIAMETRICS_AUDIODEVICECONNECTION_REPORTED, str);
     }
 }
 
@@ -1355,10 +1355,10 @@
                     << "(" << sharingModeRequestedStr << ")";
 
     if (mAudioAnalytics.mDeliverStatistics) {
-        android::util::BytesField bf_serialized(
+        const stats::media_metrics::BytesField bf_serialized(
             serializedDeviceTypes.c_str(), serializedDeviceTypes.size());
         const auto result = sendToStatsd(
-                CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
                 , path
                 , direction
                 , framesPerBurst
@@ -1381,7 +1381,7 @@
         std::stringstream ss;
         ss << "result:" << result;
         const auto fieldsStr = printFields(AAudioStreamFields,
-                CONDITION(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED)
                 , path
                 , direction
                 , framesPerBurst
@@ -1404,7 +1404,7 @@
         ss << " " << fieldsStr;
         std::string str = ss.str();
         ALOGV("%s: statsd %s", __func__, str.c_str());
-        mAudioAnalytics.mStatsdLog->log(android::util::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
+        mAudioAnalytics.mStatsdLog->log(stats::media_metrics::MEDIAMETRICS_AAUDIOSTREAM_REPORTED, str);
     }
 }
 
@@ -1544,12 +1544,12 @@
 // Classifies the setting event for statsd (use generated statsd enums.proto constants).
 static int32_t classifySettingEvent(bool isSetAlready, bool withinBoot) {
     if (isSetAlready) {
-        return util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_NORMAL;
+        return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_NORMAL;
     }
     if (withinBoot) {
-        return util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_BOOT;
+        return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_BOOT;
     }
-    return util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_FIRST;
+    return stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__EVENT__SPATIALIZER_SETTING_EVENT_FIRST;
 }
 
 void AudioAnalytics::Spatializer::onEvent(
@@ -1598,7 +1598,7 @@
                 types::channelMaskVectorFromString(channelMasks);
 
         const auto [ result, str ] = sendToStatsd(SpatializerCapabilitiesFields,
-                CONDITION(android::util::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED)
+                CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED)
                 , headTrackingModesVector
                 , levelsVector
                 , modesVector
@@ -1606,7 +1606,7 @@
                 );
 
         mAudioAnalytics.mStatsdLog->log(
-                android::util::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED, str);
+                stats::media_metrics::MEDIAMETRICS_SPATIALIZERCAPABILITIES_REPORTED, str);
 
         std::lock_guard lg(mLock);
         if (mFirstCreateTimeNs == 0) {
@@ -1655,13 +1655,13 @@
                 deviceState.enabled = enabled;
                 const bool enabledStatsd = enabled == "true";
                 const auto [ result, str ] = sendToStatsd(SpatializerDeviceEnabledFields,
-                        CONDITION(android::util::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED)
+                        CONDITION(stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED)
                         , deviceTypeStatsd
                         , settingEventStatsd
                         , enabledStatsd
                         );
                 mAudioAnalytics.mStatsdLog->log(
-                        android::util::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED, str);
+                        stats::media_metrics::MEDIAMETRICS_SPATIALIZERDEVICEENABLED_REPORTED, str);
             }
         }
         if (!hasHeadTracker.empty()) {
@@ -1671,13 +1671,13 @@
                 deviceState.hasHeadTracker = hasHeadTracker;
                 const bool supportedStatsd = hasHeadTracker == "true";
                 const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceSupportedFields,
-                        CONDITION(android::util::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED)
+                        CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED)
                         , deviceTypeStatsd
                         , settingEventStatsd
                         , supportedStatsd
                         );
                 mAudioAnalytics.mStatsdLog->log(
-                        android::util::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED, str);
+                        stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICESUPPORTED_REPORTED, str);
             }
         }
         if (!headTrackerEnabled.empty()) {
@@ -1687,13 +1687,13 @@
                 deviceState.headTrackerEnabled = headTrackerEnabled;
                 const bool enabledStatsd = headTrackerEnabled == "true";
                 const auto [ result, str ] = sendToStatsd(HeadTrackerDeviceEnabledFields,
-                        CONDITION(android::util::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED)
+                        CONDITION(stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED)
                         , deviceTypeStatsd
                         , settingEventStatsd
                         , enabledStatsd
                         );
                 mAudioAnalytics.mStatsdLog->log(
-                        android::util::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED, str);
+                        stats::media_metrics::MEDIAMETRICS_HEADTRACKERDEVICEENABLED_REPORTED, str);
             }
         }
         mSimpleLog.log("%s deviceKey: %s item: %s",
diff --git a/services/mediametrics/AudioPowerUsage.cpp b/services/mediametrics/AudioPowerUsage.cpp
index 5787e9e..630a436 100644
--- a/services/mediametrics/AudioPowerUsage.cpp
+++ b/services/mediametrics/AudioPowerUsage.cpp
@@ -26,7 +26,7 @@
 #include <string>
 #include <audio_utils/clock.h>
 #include <cutils/properties.h>
-#include <statslog.h>
+#include <stats_media_metrics.h>
 #include <sys/timerfd.h>
 #include <system/audio.h>
 
@@ -164,7 +164,7 @@
     const int32_t duration_secs = (int32_t)(duration_ns / NANOS_PER_SECOND);
     const int32_t min_volume_duration_secs = (int32_t)(min_volume_duration_ns / NANOS_PER_SECOND);
     const int32_t max_volume_duration_secs = (int32_t)(max_volume_duration_ns / NANOS_PER_SECOND);
-    const int result = android::util::stats_write(android::util::AUDIO_POWER_USAGE_DATA_REPORTED,
+    const int result = stats::media_metrics::stats_write(stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED,
                                          audio_device,
                                          duration_secs,
                                          (float)volume,
@@ -177,7 +177,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_audio_power_usage_data_reported:"
-            << android::util::AUDIO_POWER_USAGE_DATA_REPORTED
+            << stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED
             << " audio_device:" << audio_device
             << " duration_secs:" << duration_secs
             << " average_volume:" << (float)volume
@@ -187,7 +187,7 @@
             << " max_volume_duration_secs:" << max_volume_duration_secs
             << " max_volume:" << (float)max_volume
             << " }";
-    mStatsdLog->log(android::util::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
+    mStatsdLog->log(stats::media_metrics::AUDIO_POWER_USAGE_DATA_REPORTED, log.str());
 }
 
 void AudioPowerUsage::updateMinMaxVolumeAndDuration(
diff --git a/services/mediametrics/AudioTypes.cpp b/services/mediametrics/AudioTypes.cpp
index d2b4aab..353ae12 100644
--- a/services/mediametrics/AudioTypes.cpp
+++ b/services/mediametrics/AudioTypes.cpp
@@ -18,7 +18,7 @@
 #include "MediaMetricsConstants.h"
 #include "StringUtils.h"
 #include <media/TypeConverter.h> // requires libmedia_helper to get the Audio code.
-#include <statslog.h>            // statsd
+#include <stats_media_metrics.h>            // statsd
 
 namespace android::mediametrics::types {
 
@@ -184,41 +184,41 @@
 const std::unordered_map<std::string, int32_t>& getAudioDeviceInfoTypeMap() {
     // DO NOT MODIFY VALUES (OK to add new ones).
     static std::unordered_map<std::string, int32_t> map{
-        {"unknown", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN},
-        {"earpiece", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_EARPIECE},
-        {"speaker", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER},
-        {"headset", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADSET},
-        {"headphone", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADPHONES}, // sic
-        {"bt_sco", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
-        {"bt_sco_hs", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
-        {"bt_sco_carkit", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
-        {"bt_a2dp", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
-        {"bt_a2dp_hp", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
-        {"bt_a2dp_spk", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
-        {"aux_digital", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
-        {"hdmi", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
-        {"analog_dock", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
-        {"digital_dock", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
-        {"usb_accessory", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_ACCESSORY},
-        {"usb_device", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_DEVICE},
-        {"usb_headset", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_HEADSET},
-        {"remote_submix", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_REMOTE_SUBMIX},
-        {"telephony_tx", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_TELEPHONY},
-        {"line", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_ANALOG},
-        {"hdmi_arc", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_ARC},
-        {"hdmi_earc", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_EARC},
-        {"spdif", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_DIGITAL},
-        {"fm_transmitter", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_FM},
-        {"aux_line", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_AUX_LINE},
-        {"speaker_safe", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER_SAFE},
-        {"ip", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_IP},
-        {"bus", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUS},
-        {"proxy", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN /* AUDIO_DEVICE_INFO_TYPE_PROXY */},
-        {"hearing_aid_out", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HEARING_AID},
-        {"echo_canceller", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_ECHO_REFERENCE}, // sic
-        {"ble_headset", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_HEADSET},
-        {"ble_speaker", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_SPEAKER},
-        {"ble_broadcast", util::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_BROADCAST},
+        {"unknown", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN},
+        {"earpiece", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_EARPIECE},
+        {"speaker", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER},
+        {"headset", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADSET},
+        {"headphone", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_WIRED_HEADPHONES}, // sic
+        {"bt_sco", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
+        {"bt_sco_hs", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
+        {"bt_sco_carkit", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_SCO},
+        {"bt_a2dp", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
+        {"bt_a2dp_hp", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
+        {"bt_a2dp_spk", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLUETOOTH_A2DP},
+        {"aux_digital", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
+        {"hdmi", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI},
+        {"analog_dock", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
+        {"digital_dock", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_DOCK},
+        {"usb_accessory", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_ACCESSORY},
+        {"usb_device", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_DEVICE},
+        {"usb_headset", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_USB_HEADSET},
+        {"remote_submix", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_REMOTE_SUBMIX},
+        {"telephony_tx", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_TELEPHONY},
+        {"line", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_ANALOG},
+        {"hdmi_arc", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_ARC},
+        {"hdmi_earc", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HDMI_EARC},
+        {"spdif", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_LINE_DIGITAL},
+        {"fm_transmitter", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_FM},
+        {"aux_line", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_AUX_LINE},
+        {"speaker_safe", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUILTIN_SPEAKER_SAFE},
+        {"ip", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_IP},
+        {"bus", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BUS},
+        {"proxy", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_UNKNOWN /* AUDIO_DEVICE_INFO_TYPE_PROXY */},
+        {"hearing_aid_out", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_HEARING_AID},
+        {"echo_canceller", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_ECHO_REFERENCE}, // sic
+        {"ble_headset", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_HEADSET},
+        {"ble_speaker", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_SPEAKER},
+        {"ble_broadcast", stats::media_metrics::MEDIAMETRICS_SPATIALIZER_DEVICE_ENABLED_REPORTED__TYPE__AUDIO_DEVICE_INFO_TYPE_BLE_BROADCAST},
     };
     return map;
 }
@@ -324,23 +324,23 @@
     // DO NOT MODIFY VALUES(OK to add new ones).
     static std::unordered_map<std::string, int32_t> map {
         {"",
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_OK,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__NO_ERROR},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_ARGUMENT,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_ARGUMENT},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_ARGUMENT},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_IO,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_IO},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_IO},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_MEMORY,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_MEMORY},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_MEMORY},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_SECURITY,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_SECURITY},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_SECURITY},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_STATE,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_STATE},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_STATE},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_TIMEOUT,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_TIMEOUT},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_TIMEOUT},
         {AMEDIAMETRICS_PROP_STATUS_VALUE_UNKNOWN,
-            util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN},
+            stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN},
     };
     return map;
 }
@@ -664,7 +664,7 @@
     auto& map = getStatusMap();
     auto it = map.find(status);
     if (it == map.end()) {
-        return util::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN;
+        return stats::media_metrics::MEDIAMETRICS_AUDIO_TRACK_STATUS_REPORTED__STATUS__ERROR_UNKNOWN;
     }
     return it->second;
 }
diff --git a/services/mediametrics/MediaDrmStatsdHelper.cpp b/services/mediametrics/MediaDrmStatsdHelper.cpp
new file mode 100644
index 0000000..d762672
--- /dev/null
+++ b/services/mediametrics/MediaDrmStatsdHelper.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "MediaDrmStatsdHelper.h"
+#include <tuple>
+#include <map>
+#include <unordered_map>
+
+namespace {
+
+struct UUID {
+    uint64_t msb, lsb; // NOLINT(misc-non-private-member-variables-in-classes)
+    bool operator < (const UUID& that) const {
+        return std::tie(msb, lsb) < std::tie(that.msb, that.lsb);
+    }
+};
+
+// KEEP IN SYNC WITH frameworks/proto_logging/stats/enums/media/drm/enums.proto
+std::map<UUID, int32_t> const kUuidSchemeEnumMap {
+    {{.msb = 0x6DD8B3C345F44A68, .lsb = 0xBF3A64168D01A4A6}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ABV_MODRM             }, // ABV_MODRM
+    {{.msb = 0xF239E769EFA34850, .lsb = 0x9C16A903C6932EFB}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ADOBE_PRIMETIME       }, // ADOBE_PRIMETIME
+    {{.msb = 0x616C746963617374, .lsb = 0x2D50726F74656374}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ALTICAST              }, // ALTICAST
+    {{.msb = 0x94CE86FB07FF4F43, .lsb = 0xADB893D2FA968CA2}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__APPLE_FAIRPLAY        }, // APPLE_FAIRPLAY
+    {{.msb = 0x279FE473512C48FE, .lsb = 0xADE8D176FEE6B40F}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__ARRIS_TITANIUM        }, // ARRIS_TITANIUM
+    {{.msb = 0x3D5E6D359B9A41E8, .lsb = 0xB843DD3C6E72C42C}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CHINADRM              }, // CHINADRM
+    {{.msb = 0x3EA8778F77424BF9, .lsb = 0xB18BE834B2ACBD47}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CLEAR_KEY_AES_128     }, // CLEAR_KEY_AES_128
+    {{.msb = 0xBE58615B19C44684, .lsb = 0x88B3C8C57E99E957}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CLEAR_KEY_SAMPLE_AES  }, // CLEAR_KEY_SAMPLE_AES
+    {{.msb = 0xE2719D58A985B3C9, .lsb = 0x781AB030AF78D30E}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CLEAR_KEY_DASH_IF     }, // CLEAR_KEY_DASH_IF
+    {{.msb = 0x644FE7B5260F4FAD, .lsb = 0x949A0762FFB054B4}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CMLA_OMA              }, // CMLA_OMA
+    {{.msb = 0x37C332587B994C7E, .lsb = 0xB15D19AF74482154}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__COMMSCOPE_TITANIUM    }, // COMMSCOPE_TITANIUM
+    {{.msb = 0x45D481CB8FE049C0, .lsb = 0xADA9AB2D2455B2F2}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__CORECRYPT             }, // CORECRYPT
+    {{.msb = 0xDCF4E3E362F15818, .lsb = 0x7BA60A6FE33FF3DD}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__DIGICAP_SMARTXESS     }, // DIGICAP_SMARTXESS
+    {{.msb = 0x35BF197B530E42D7, .lsb = 0x8B651B4BF415070F}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__DIVX                  }, // DIVX
+    {{.msb = 0x80A6BE7E14484C37, .lsb = 0x9E70D5AEBE04C8D2}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__IRDETO                }, // IRDETO
+    {{.msb = 0x5E629AF538DA4063, .lsb = 0x897797FFBD9902D4}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__MARLIN                }, // MARLIN
+    {{.msb = 0x9A04F07998404286, .lsb = 0xAB92E65BE0885F95}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__MICROSOFT_PLAYREADY   }, // MICROSOFT_PLAYREADY
+    {{.msb = 0x6A99532D869F5922, .lsb = 0x9A91113AB7B1E2F3}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__MOBITV                }, // MOBITV
+    {{.msb = 0xADB41C242DBF4A6D, .lsb = 0x958B4457C0D27B95}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__NAGRA_MEDIAACCESS     }, // NAGRA_MEDIAACCESS
+    {{.msb = 0x1F83E1E86EE94F0D, .lsb = 0xBA2F5EC4E3ED1A66}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__SECUREMEDIA           }, // SECUREMEDIA
+    {{.msb = 0x992C46E6C4374899, .lsb = 0xB6A050FA91AD0E39}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__SECUREMEDIA_STEELKNOT }, // SECUREMEDIA_STEELKNOT
+    {{.msb = 0xA68129D3575B4F1A, .lsb = 0x9CBA3223846CF7C3}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__SYNAMEDIA_VIDEOGUARD  }, // SYNAMEDIA_VIDEOGUARD
+    {{.msb = 0xAA11967FCC014A4A, .lsb = 0x8E99C5D3DDDFEA2D}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__UNITEND_UDRM          }, // UNITEND_UDRM
+    {{.msb = 0x9A27DD82FDE24725, .lsb = 0x8CBC4234AA06EC09}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__VERIMATRIX_VCAS       }, // VERIMATRIX_VCAS
+    {{.msb = 0xB4413586C58CFFB0, .lsb = 0x94A5D4896C1AF6C3}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__VIACCESS_ORCA         }, // VIACCESS_ORCA
+    {{.msb = 0x793B79569F944946, .lsb = 0xA94223E7EF7E44B4}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__VISIONCRYPT           }, // VISIONCRYPT
+    {{.msb = 0x1077EFECC0B24D02, .lsb = 0xACE33C1E52E2FB4B}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__W3C_COMMON            }, // W3C_COMMON
+    {{.msb = 0xEDEF8BA979D64ACE, .lsb = 0xA3C827DCD51D21ED}, android::stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__WIDEVINE              }, // WIDEVINE
+};
+
+// KEEP IN SYNC WITH frameworks/av/drm/libmediadrm/include/mediadrm/IDrm.h
+// KEEP IN SYNC WITH frameworks/proto_logging/stats/enums/media/drm/enums.proto
+std::unordered_map<std::string, int32_t> const kDrmApiEnumMap {
+    {"initCheck"                  , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_INIT_CHECK                      },
+    {"isCryptoSchemeSupported"    , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_IS_CRYPTO_SCHEME_SUPPORTED      },
+    {"createPlugin"               , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_CREATE_PLUGIN                   },
+    {"destroyPlugin"              , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_DESTROY_PLUGIN                  },
+    {"openSession"                , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_OPEN_SESSION                    },
+    {"closeSession"               , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_CLOSE_SESSION                   },
+    {"getKeyRequest"              , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_KEY_REQUEST                 },
+    {"provideKeyResponse"         , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_PROVIDE_KEY_RESPONSE            },
+    {"removeKeys"                 , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_KEYS                     },
+    {"restoreKeys"                , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_RESTORE_KEYS                    },
+    {"queryKeyStatus"             , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_QUERY_KEY_STATUS                },
+    {"getProvisionRequest"        , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_PROVISION_REQUEST           },
+    {"provideProvisionResponse"   , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_PROVIDE_PROVISION_RESPONSE      },
+    {"getSecureStops"             , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURE_STOPS                },
+    {"getSecureStopIds"           , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURE_STOP_IDS             },
+    {"getSecureStop"              , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURE_STOP                 },
+    {"releaseSecureStops"         , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_RELEASE_SECURE_STOPS            },
+    {"removeSecureStop"           , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_SECURE_STOP              },
+    {"removeAllSecureStops"       , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_ALL_SECURE_STOPS         },
+    {"getHdcpLevels"              , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_HDCP_LEVELS                 },
+    {"getNumberOfSessions"        , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_NUMBER_OF_SESSIONS          },
+    {"getSecurityLevel"           , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SECURITY_LEVEL              },
+    {"getOfflineLicenseKeySetIds" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_OFFLINE_LICENSE_KEY_SET_IDS },
+    {"removeOfflineLicense"       , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REMOVE_OFFLINE_LICENSE          },
+    {"getOfflineLicenseState"     , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_OFFLINE_LICENSE_STATE       },
+    {"getPropertyString"          , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_PROPERTY_STRING             },
+    {"getPropertyByteArray"       , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_PROPERTY_BYTE_ARRAY         },
+    {"setPropertyString"          , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_PROPERTY_STRING             },
+    {"setPropertyByteArray"       , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_PROPERTY_BYTE_ARRAY         },
+    {"getMetrics"                 , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_METRICS                     },
+    {"setCipherAlgorithm"         , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_CIPHER_ALGORITHM            },
+    {"setMacAlgorithm"            , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_MAC_ALGORITHM               },
+    {"encrypt"                    , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_ENCRYPT                 },
+    {"decrypt"                    , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_DECRYPT                 },
+    {"sign"                       , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_SIGN                    },
+    {"verify"                     , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GENERIC_VERIFY                  },
+    {"signRSA"                    , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SIGN_RSA                        },
+    {"setListener"                , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_LISTENER                    },
+    {"requiresSecureDecoder"      , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REQUIRES_SECURE_DECODER         },
+    {"requiresSecureDecoderLevel" , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_REQUIRES_SECURE_DECODER_LEVEL   },
+    {"setPlaybackId"              , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_SET_PLAYBACK_ID                 },
+    {"getLogMessages"             , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_LOG_MESSAGES                },
+    {"getSupportedSchemes"        , android::stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_GET_SUPPORTED_SCHEMES           },
+};
+
+} // anonymous namespace
+
+namespace android {
+
+int32_t MediaDrmStatsdHelper::findDrmScheme(const int64_t msb, const int64_t lsb) {
+    auto it = kUuidSchemeEnumMap.find({.msb = static_cast<uint64_t>(msb), .lsb = static_cast<uint64_t>(lsb)});
+    if (it == kUuidSchemeEnumMap.end()) return stats::media_metrics::MEDIA_DRM_SESSION_OPENED__SCHEME__DRM_SCHEME_OTHER;
+    return it->second;
+}
+
+int32_t MediaDrmStatsdHelper::findDrmApi(const std::string& api) {
+    auto it = kDrmApiEnumMap.find(api);
+    if (it == kDrmApiEnumMap.end()) return stats::media_metrics::MEDIA_DRM_ERRORED__API__DRM_API_UNKNOWN;
+    return it->second;
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index 8a7e8a9..adb2217 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -33,7 +33,7 @@
 #include <mediautils/MemoryLeakTrackUtil.h>
 #include <memunreachable/memunreachable.h>
 #include <private/android_filesystem_config.h> // UID
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include <set>
 
@@ -72,6 +72,7 @@
 bool MediaMetricsService::useUidForPackage(
         const std::string& package, const std::string& installer)
 {
+    // NOLINTBEGIN(bugprone-branch-clone)
     if (strchr(package.c_str(), '.') == nullptr) {
         return false;  // not of form 'com.whatever...'; assume internal and ok
     } else if (strncmp(package.c_str(), "android.", 8) == 0) {
@@ -85,6 +86,7 @@
     } else {
         return true;  // we're not sure where it came from, use uid only.
     }
+    // NOLINTEND(bugprone-branch-clone)
 }
 
 /* static */
@@ -509,6 +511,8 @@
     const std::string &key = item->getKey();
     if (startsWith(key, "audio.")) return true;
     if (startsWith(key, "drm.vendor.")) return true;
+    if (startsWith(key, "mediadrm.")) return true;
+
     // the list of allowedKey uses statsd_handlers
     // in iface_statsd.cpp as reference
     // drmmanager is from a trusted uid, therefore not needed here
@@ -544,7 +548,7 @@
     if (mStatsdRegistered.test_and_set()) {
         return;
     }
-    auto tag = android::util::MEDIA_DRM_ACTIVITY_INFO;
+    auto tag = stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO;
     auto cb = MediaMetricsService::pullAtomCallback;
     AStatsManager_setPullAtomCallback(tag, /* metadata */ nullptr, cb, this);
 }
@@ -562,7 +566,7 @@
 std::string MediaMetricsService::atomTagToKey(int32_t atomTag)
 {
     switch (atomTag) {
-    case android::util::MEDIA_DRM_ACTIVITY_INFO:
+    case stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO:
         return "mediadrm";
     }
     return {};
diff --git a/services/mediametrics/fuzzer/Android.bp b/services/mediametrics/fuzzer/Android.bp
index 84d494e..8b33f10 100644
--- a/services/mediametrics/fuzzer/Android.bp
+++ b/services/mediametrics/fuzzer/Android.bp
@@ -51,7 +51,7 @@
         "libprotobuf-cpp-lite",
         "libstagefright",
         "libstagefright_foundation",
-        "libstatslog",
+        "libstats_media_metrics",
         "libstatspull",
         "libstatssocket",
         "libutils",
diff --git a/services/mediametrics/iface_statsd.cpp b/services/mediametrics/iface_statsd.cpp
index 776f878..7f4e6e8 100644
--- a/services/mediametrics/iface_statsd.cpp
+++ b/services/mediametrics/iface_statsd.cpp
@@ -37,8 +37,6 @@
 #include "MediaMetricsService.h"
 #include "iface_statsd.h"
 
-#include <statslog.h>
-
 namespace android {
 
 // set of routines that crack a mediametrics::Item
@@ -85,6 +83,9 @@
         { "drmmanager", statsd_drmmanager },
         { "extractor", statsd_extractor },
         { "mediadrm", statsd_mediadrm },
+        { "mediadrm.created", statsd_mediadrm_created },
+        { "mediadrm.errored", statsd_mediadrm_errored },
+        { "mediadrm.session_opened", statsd_mediadrm_session_opened },
         { "mediaparser", statsd_mediaparser },
         { "nuplayer", statsd_nuplayer },
         { "nuplayer2", statsd_nuplayer },
diff --git a/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
index b7215e6..6e5a5cf 100644
--- a/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
+++ b/services/mediametrics/include/mediametricsservice/AudioPowerUsage.h
@@ -50,7 +50,7 @@
      */
     std::pair<std::string, int32_t> dump(int32_t lines = INT32_MAX) const;
 
-    // align with message AudioUsageDataReported in frameworks/base/cmds/statsd/src/atoms.proto
+    // align with message AudioPowerUsageDataReported in frameworks/proto_logging/stats/atoms.proto
     enum AudioType {
         UNKNOWN_TYPE = 0,
         VOICE_CALL_TYPE = 1,            // voice call
diff --git a/services/mediametrics/include/mediametricsservice/MediaDrmStatsdHelper.h b/services/mediametrics/include/mediametricsservice/MediaDrmStatsdHelper.h
new file mode 100644
index 0000000..2e5e7ff
--- /dev/null
+++ b/services/mediametrics/include/mediametricsservice/MediaDrmStatsdHelper.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_DRM_STATSD_HELPER_H
+#define MEDIA_DRM_STATSD_HELPER_H
+
+#include <cstdint>
+#include <stats_media_metrics.h>
+#include <string>
+namespace android {
+
+class MediaDrmStatsdHelper {
+public:
+    static int32_t findDrmScheme(const int64_t msb, const int64_t lsb);
+    static int32_t findDrmApi(const std::string& api);
+};
+
+} // namespace android
+#endif  // MEDIA_DRM_STATSD_HELPER_H
\ No newline at end of file
diff --git a/services/mediametrics/include/mediametricsservice/iface_statsd.h b/services/mediametrics/include/mediametricsservice/iface_statsd.h
index c2a8b3c..5bc293b 100644
--- a/services/mediametrics/include/mediametricsservice/iface_statsd.h
+++ b/services/mediametrics/include/mediametricsservice/iface_statsd.h
@@ -30,13 +30,15 @@
 extern statsd_pusher statsd_audiothread;
 extern statsd_pusher statsd_audiotrack;
 extern statsd_pusher statsd_codec;
+extern statsd_pusher statsd_drmmanager;
 extern statsd_pusher statsd_extractor;
+extern statsd_pusher statsd_mediadrm;
+extern statsd_pusher statsd_mediadrm_created;
+extern statsd_pusher statsd_mediadrm_errored;
+extern statsd_pusher statsd_mediadrm_session_opened;
 extern statsd_pusher statsd_mediaparser;
-
 extern statsd_pusher statsd_nuplayer;
 extern statsd_pusher statsd_recorder;
-extern statsd_pusher statsd_mediadrm;
-extern statsd_pusher statsd_drmmanager;
 
 using statsd_puller = bool (const std::shared_ptr<const mediametrics::Item>& item,
         AStatsEventList *, const std::shared_ptr<mediametrics::StatsdLog>& statsdLog);
diff --git a/services/mediametrics/statsd_audiopolicy.cpp b/services/mediametrics/statsd_audiopolicy.cpp
index 3d9376e..9a9bc1d 100644
--- a/services/mediametrics/statsd_audiopolicy.cpp
+++ b/services/mediametrics/statsd_audiopolicy.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
@@ -107,15 +107,16 @@
         return false;
     }
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_AUDIOPOLICY_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         bf_serialized);
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_audiopolicy_reported:"
-            << android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_AUDIOPOLICY_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -131,7 +132,7 @@
             << " active_session:" << active_session
             << " active_device:" << active_device
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_AUDIOPOLICY_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOPOLICY_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_audiorecord.cpp b/services/mediametrics/statsd_audiorecord.cpp
index a7b045e..63c61ec 100644
--- a/services/mediametrics/statsd_audiorecord.cpp
+++ b/services/mediametrics/statsd_audiorecord.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "ValidateId.h"
@@ -99,16 +99,14 @@
     }
 
     int32_t error_code = -1;
-    if (item->getInt32("android.media.audiorecord.errcode", &error_code)) {
-        metrics_proto.set_error_code(error_code);
-    } else if (item->getInt32("android.media.audiorecord.lastError.code", &error_code)) {
+    if (item->getInt32("android.media.audiorecord.errcode", &error_code) ||
+        item->getInt32("android.media.audiorecord.lastError.code", &error_code)) {
         metrics_proto.set_error_code(error_code);
     }
 
     std::string error_function;
-    if (item->getString("android.media.audiorecord.errfunc", &error_function)) {
-        metrics_proto.set_error_function(error_function);
-    } else if (item->getString("android.media.audiorecord.lastError.at", &error_function)) {
+    if (item->getString("android.media.audiorecord.errfunc", &error_function) ||
+        item->getString("android.media.audiorecord.lastError.at", &error_function)) {
         metrics_proto.set_error_function(error_function);
     }
 
@@ -149,8 +147,9 @@
     (void)item->getString("android.media.audiorecord.logSessionId", &logSessionId);
     const auto log_session_id = mediametrics::ValidateId::get()->validateId(logSessionId);
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIORECORD_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_AUDIORECORD_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         bf_serialized,
@@ -158,7 +157,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_audiorecord_reported:"
-            << android::util::MEDIAMETRICS_AUDIORECORD_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_AUDIORECORD_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -183,7 +182,7 @@
 
             << " log_session_id:" << log_session_id
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_AUDIORECORD_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIORECORD_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_audiothread.cpp b/services/mediametrics/statsd_audiothread.cpp
index e9b6dd6..3056605 100644
--- a/services/mediametrics/statsd_audiothread.cpp
+++ b/services/mediametrics/statsd_audiothread.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
@@ -188,15 +188,16 @@
         return false;
     }
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_AUDIOTHREAD_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         bf_serialized);
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_audiothread_reported:"
-            << android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_AUDIOTHREAD_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -231,7 +232,7 @@
             << " latency_mean_millis:" << latency_mean_millis
             << " latency_stddev_millis:" << latency_stddev_millis
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_AUDIOTHREAD_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTHREAD_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_audiotrack.cpp b/services/mediametrics/statsd_audiotrack.cpp
index 67514e9..1fc7fb4 100644
--- a/services/mediametrics/statsd_audiotrack.cpp
+++ b/services/mediametrics/statsd_audiotrack.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "ValidateId.h"
@@ -134,8 +134,9 @@
     (void)item->getString("android.media.audiotrack.logSessionId", &logSessionId);
     const auto log_session_id = mediametrics::ValidateId::get()->validateId(logSessionId);
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+                               stats::media_metrics::MEDIAMETRICS_AUDIOTRACK_REPORTED,
                                timestamp_nanos, package_name.c_str(), package_version_code,
                                media_apex_version,
                                bf_serialized,
@@ -143,7 +144,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_audiotrack_reported:"
-            << android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_AUDIOTRACK_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -164,7 +165,7 @@
 
             << " log_session_id:" << log_session_id
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_AUDIOTRACK_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_AUDIOTRACK_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_codec.cpp b/services/mediametrics/statsd_codec.cpp
index a737ba0..c5957e9 100644
--- a/services/mediametrics/statsd_codec.cpp
+++ b/services/mediametrics/statsd_codec.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 #include <stats_event.h>
 
 #include "cleaner.h"
@@ -46,7 +46,7 @@
     if (item == nullptr) return false;
 
     AStatsEvent* event = AStatsEvent_obtain();
-    AStatsEvent_setAtomId(event, android::util::MEDIA_CODEC_REPORTED);
+    AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_CODEC_REPORTED);
 
     const nsecs_t timestamp_nanos = MediaMetricsService::roundTime(item->getTimestamp());
     AStatsEvent_writeInt64(event, timestamp_nanos);
@@ -455,8 +455,8 @@
         ALOGE("Failed to serialize codec metrics");
         return false;
     }
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_CODEC_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED,
                                timestamp_nanos, package_name.c_str(), package_version_code,
                                media_apex_version,
                                bf_serialized);
@@ -464,7 +464,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_codec_reported:"
-            << android::util::MEDIAMETRICS_CODEC_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -525,7 +525,7 @@
             << " original_qp_b_min:" << qpBMinOri
             << " original_qp_b_max:" << qpBMaxOri
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_CODEC_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_CODEC_REPORTED, log.str());
 
 
     return true;
diff --git a/services/mediametrics/statsd_drm.cpp b/services/mediametrics/statsd_drm.cpp
index e06a605..9f08eca 100644
--- a/services/mediametrics/statsd_drm.cpp
+++ b/services/mediametrics/statsd_drm.cpp
@@ -18,8 +18,9 @@
 #define LOG_TAG "statsd_drm"
 #include <utils/Log.h>
 #include <media/stagefright/foundation/base64.h>
+#include <binder/IPCThreadState.h>
 
-#include <stdint.h>
+#include <cstdint>
 #include <inttypes.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -32,10 +33,11 @@
 #include <pwd.h>
 
 #include "MediaMetricsService.h"
+#include "MediaDrmStatsdHelper.h"
 #include "StringUtils.h"
 #include "iface_statsd.h"
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include <array>
 #include <string>
@@ -69,8 +71,9 @@
     // This field is left here for backward compatibility.
     // This field is not used anymore.
     const std::string  kUnusedField("");
-    android::util::BytesField bf_serialized(kUnusedField.c_str(), kUnusedField.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIADRM_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized(kUnusedField.c_str(), kUnusedField.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_MEDIADRM_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         vendor.c_str(),
@@ -80,7 +83,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_mediadrm_reported:"
-            << android::util::MEDIAMETRICS_MEDIADRM_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_MEDIADRM_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -90,7 +93,7 @@
             << " description:" << description
             // omitting serialized
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_MEDIADRM_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_MEDIADRM_REPORTED, log.str());
     return true;
 }
 
@@ -122,7 +125,8 @@
         item->getInt64(("method"s + std::to_string(i)).c_str(), &methodCounts[i]);
     }
 
-    const int result = android::util::stats_write(android::util::MEDIAMETRICS_DRMMANAGER_REPORTED,
+    const int result = stats::media_metrics::stats_write(
+                               stats::media_metrics::MEDIAMETRICS_DRMMANAGER_REPORTED,
                                timestamp_nanos, package_name.c_str(), package_version_code,
                                media_apex_version,
                                plugin_id.c_str(), description.c_str(),
@@ -136,7 +140,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_drmmanager_reported:"
-            << android::util::MEDIAMETRICS_DRMMANAGER_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_DRMMANAGER_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -151,7 +155,7 @@
         log << " method_" << i << ":" << methodCounts[i];
     }
     log << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_DRMMANAGER_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_DRMMANAGER_REPORTED, log.str());
     return true;
 }
 
@@ -207,7 +211,7 @@
 
     // Memory for |event| is internally managed by statsd.
     AStatsEvent* event = AStatsEventList_addStatsEvent(out);
-    AStatsEvent_setAtomId(event, android::util::MEDIA_DRM_ACTIVITY_INFO);
+    AStatsEvent_setAtomId(event, stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO);
     AStatsEvent_writeString(event, item->getPkgName().c_str());
     AStatsEvent_writeInt64(event, item->getPkgVersionCode());
     AStatsEvent_writeString(event, vendor.c_str());
@@ -219,7 +223,7 @@
     std::stringstream log;
     log << "pulled:" << " {"
             << " media_drm_activity_info:"
-            << android::util::MEDIA_DRM_ACTIVITY_INFO
+            << stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO
             << " package_name:" << item->getPkgName()
             << " package_version_code:" << item->getPkgVersionCode()
             << " vendor:" << vendor
@@ -227,7 +231,146 @@
             << " framework_metrics:" << mediametrics::stringutils::bytesToString(framework_raw, 8)
             << " vendor_metrics:" <<  mediametrics::stringutils::bytesToString(plugin_raw, 8)
             << " }";
-    statsdLog->log(android::util::MEDIA_DRM_ACTIVITY_INFO, log.str());
+    statsdLog->log(stats::media_metrics::MEDIA_DRM_ACTIVITY_INFO, log.str());
+    return true;
+}
+
+bool statsd_mediadrm_created(const std::shared_ptr<const mediametrics::Item>& item,
+        const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+    int64_t uuid_lsb = -1;
+    if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+    int64_t uuid_msb = -1;
+    if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+    const int32_t scheme = MediaDrmStatsdHelper::findDrmScheme(uuid_msb, uuid_lsb);
+    const int32_t uid = IPCThreadState::self()->getCallingUid();
+    int32_t frontend = 0;
+    if (!item->getInt32("frontend", &frontend)) return false;
+
+    // Optional to be included
+    std::string version = "";
+    item->getString("version", &version);
+    const int result = stats_write(stats::media_metrics::MEDIA_DRM_CREATED,
+                    scheme, uuid_lsb, uuid_msb, uid, frontend, version.c_str());
+
+    std::stringstream log;
+    log << "result:" << result << " {"
+            << " media_drm_created:"
+            << stats::media_metrics::MEDIA_DRM_CREATED
+            << " scheme:" << scheme
+            << " uuid_lsb:" << uuid_lsb
+            << " uuid_msb:" << uuid_msb
+            << " uid:" << uid
+            << " frontend:" << frontend
+            << " version:" << version
+            << " }";
+    statsdLog->log(stats::media_metrics::MEDIA_DRM_CREATED, log.str());
+    return true;
+}
+
+bool statsd_mediadrm_session_opened(const std::shared_ptr<const mediametrics::Item>& item,
+        const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+    int64_t uuid_lsb = -1;
+    if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+    int64_t uuid_msb = -1;
+    if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+    const int32_t scheme = MediaDrmStatsdHelper::findDrmScheme(uuid_msb, uuid_lsb);
+    std::string object_nonce = "";
+    if (!item->getString("object_nonce", &object_nonce)) return false;
+    const int32_t uid = IPCThreadState::self()->getCallingUid();
+    int32_t frontend = 0;
+    if (!item->getInt32("frontend", &frontend)) return false;
+    int32_t requested_security_level = -1;
+    if (!item->getInt32("requested_security_level", &requested_security_level)) return false;
+    int32_t opened_security_level = -1;
+    if (!item->getInt32("opened_security_level", &opened_security_level)) return false;
+
+    // Optional to be included
+    std::string version = "";
+    item->getString("version", &version);
+    const int result = stats_write(stats::media_metrics::MEDIA_DRM_SESSION_OPENED,
+                        scheme, uuid_lsb, uuid_msb, uid, frontend, version.c_str(),
+                        object_nonce.c_str(), requested_security_level,
+                        opened_security_level);
+
+    std::stringstream log;
+    log << "result:" << result << " {"
+            << " media_drm_session_opened:"
+            << stats::media_metrics::MEDIA_DRM_SESSION_OPENED
+            << " scheme:" << scheme
+            << " uuid_lsb:" << uuid_lsb
+            << " uuid_msb:" << uuid_msb
+            << " uid:" << uid
+            << " frontend:" << frontend
+            << " version:" << version
+            << " object_nonce:" << object_nonce
+            << " requested_security_level:" << requested_security_level
+            << " opened_security_level:" << opened_security_level
+            << " }";
+    statsdLog->log(stats::media_metrics::MEDIA_DRM_SESSION_OPENED, log.str());
+    return true;
+}
+
+bool statsd_mediadrm_errored(const std::shared_ptr<const mediametrics::Item>& item,
+        const std::shared_ptr<mediametrics::StatsdLog>& statsdLog)
+{
+    int64_t uuid_lsb = -1;
+    if (!item->getInt64("uuid_lsb", &uuid_lsb)) return false;
+    int64_t uuid_msb = -1;
+    if (!item->getInt64("uuid_msb", &uuid_msb)) return false;
+    const int32_t scheme = MediaDrmStatsdHelper::findDrmScheme(uuid_msb, uuid_lsb);
+    const int32_t uid = IPCThreadState::self()->getCallingUid();
+    int32_t frontend = 0;
+    if (!item->getInt32("frontend", &frontend)) return false;
+    std::string object_nonce = "";
+    if (!item->getString("object_nonce", &object_nonce)) return false;
+    int32_t security_level = -1;
+    if (!item->getInt32("security_level", &security_level)) return false;
+    std::string api_str = "";
+    if (!item->getString("api", &api_str)) return false;
+    const int32_t api = MediaDrmStatsdHelper::findDrmApi(api_str);
+    int32_t error_code = -1;
+    if (!item->getInt32("error_code", &error_code)) return false;
+
+    // Optional to be included
+    std::string version = "";
+    item->getString("version", &version);
+    std::string session_nonce = "";
+    item->getString("session_nonce", &session_nonce);
+
+    int32_t cdm_err = 0;
+    item->getInt32("cdm_err", &cdm_err);
+    int32_t oem_err = 0;
+    item->getInt32("oem_err", &oem_err);
+    int32_t error_context = -1;
+    item->getInt32("error_context", &error_context);
+
+    const int result = stats_write(stats::media_metrics::MEDIA_DRM_ERRORED, scheme, uuid_lsb,
+                        uuid_msb, uid, frontend, version.c_str(), object_nonce.c_str(),
+                        session_nonce.c_str(), security_level, api, error_code, cdm_err,
+                        oem_err, error_context);
+
+    std::stringstream log;
+    log << "result:" << result << " {"
+            << " media_drm_errored:"
+            << stats::media_metrics::MEDIA_DRM_ERRORED
+            << " scheme:" << scheme
+            << " uuid_lsb:" << uuid_lsb
+            << " uuid_msb:" << uuid_msb
+            << " uid:" << uid
+            << " frontend:" << frontend
+            << " version:" << version
+            << " object_nonce:" << object_nonce
+            << " session_nonce:" << session_nonce
+            << " security_level:" << security_level
+            << " api:" << api
+            << " error_code:" << error_code
+            << " cdm_err:" << cdm_err
+            << " oem_err:" << oem_err
+            << " error_context:" << error_context
+            << " }";
+    statsdLog->log(stats::media_metrics::MEDIA_DRM_ERRORED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_extractor.cpp b/services/mediametrics/statsd_extractor.cpp
index a8bfeaa..9345df6 100644
--- a/services/mediametrics/statsd_extractor.cpp
+++ b/services/mediametrics/statsd_extractor.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "ValidateId.h"
@@ -96,15 +96,16 @@
         return false;
     }
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_EXTRACTOR_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         bf_serialized);
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_extractor_reported:"
-            << android::util::MEDIAMETRICS_EXTRACTOR_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_EXTRACTOR_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -116,7 +117,7 @@
             << " entry_point:" << entry_point_string << "(" << entry_point << ")"
             << " log_session_id:" << log_session_id
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_EXTRACTOR_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_EXTRACTOR_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_mediaparser.cpp b/services/mediametrics/statsd_mediaparser.cpp
index 67ca874b..458bd32 100644
--- a/services/mediametrics/statsd_mediaparser.cpp
+++ b/services/mediametrics/statsd_mediaparser.cpp
@@ -28,7 +28,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "ValidateId.h"
@@ -83,7 +83,8 @@
     item->getString("android.media.mediaparser.logSessionId", &logSessionId);
     logSessionId = mediametrics::ValidateId::get()->validateId(logSessionId);
 
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED,
+    const int result = stats::media_metrics::stats_write(
+                               stats::media_metrics::MEDIAMETRICS_MEDIAPARSER_REPORTED,
                                timestamp_nanos,
                                package_name.c_str(),
                                package_version_code,
@@ -103,7 +104,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_mediaparser_reported:"
-            << android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_MEDIAPARSER_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -120,7 +121,7 @@
             << " video_height:" << videoHeight
             << " log_session_id:" << logSessionId
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_MEDIAPARSER_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_MEDIAPARSER_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_nuplayer.cpp b/services/mediametrics/statsd_nuplayer.cpp
index bdee1f2..fd545f4 100644
--- a/services/mediametrics/statsd_nuplayer.cpp
+++ b/services/mediametrics/statsd_nuplayer.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "frameworks/proto_logging/stats/message/mediametrics_message.pb.h"
@@ -153,8 +153,9 @@
         return false;
     }
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_NUPLAYER_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_NUPLAYER_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         bf_serialized);
@@ -162,7 +163,7 @@
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_nuplayer_reported:"
-            << android::util::MEDIAMETRICS_NUPLAYER_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_NUPLAYER_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -193,7 +194,7 @@
             // TODO NuPlayer - add log_session_id
             // << " log_session_id:" << log_session_id
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_NUPLAYER_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_NUPLAYER_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediametrics/statsd_recorder.cpp b/services/mediametrics/statsd_recorder.cpp
index 5f54a68..efa284b 100644
--- a/services/mediametrics/statsd_recorder.cpp
+++ b/services/mediametrics/statsd_recorder.cpp
@@ -29,7 +29,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include <statslog.h>
+#include <stats_media_metrics.h>
 
 #include "MediaMetricsService.h"
 #include "ValidateId.h"
@@ -179,15 +179,16 @@
         return false;
     }
 
-    android::util::BytesField bf_serialized( serialized.c_str(), serialized.size());
-    int result = android::util::stats_write(android::util::MEDIAMETRICS_RECORDER_REPORTED,
+    const stats::media_metrics::BytesField bf_serialized( serialized.c_str(), serialized.size());
+    const int result = stats::media_metrics::stats_write(
+        stats::media_metrics::MEDIAMETRICS_RECORDER_REPORTED,
         timestamp_nanos, package_name.c_str(), package_version_code,
         media_apex_version,
         bf_serialized);
     std::stringstream log;
     log << "result:" << result << " {"
             << " mediametrics_recorder_reported:"
-            << android::util::MEDIAMETRICS_RECORDER_REPORTED
+            << stats::media_metrics::MEDIAMETRICS_RECORDER_REPORTED
             << " timestamp_nanos:" << timestamp_nanos
             << " package_name:" << package_name
             << " package_version_code:" << package_version_code
@@ -218,7 +219,7 @@
             << " iframe_interval:" << iframe_interval
             << " log_session_id:" << log_session_id
             << " }";
-    statsdLog->log(android::util::MEDIAMETRICS_RECORDER_REPORTED, log.str());
+    statsdLog->log(stats::media_metrics::MEDIAMETRICS_RECORDER_REPORTED, log.str());
     return true;
 }
 
diff --git a/services/mediaresourcemanager/Android.bp b/services/mediaresourcemanager/Android.bp
index 5d80744..2b8245e 100644
--- a/services/mediaresourcemanager/Android.bp
+++ b/services/mediaresourcemanager/Android.bp
@@ -16,6 +16,7 @@
         "aidl/android/media/MediaResourceSubType.aidl",
         "aidl/android/media/MediaResourceParcel.aidl",
         "aidl/android/media/MediaResourcePolicyParcel.aidl",
+        "aidl/android/media/ClientInfoParcel.aidl",
     ],
     path: "aidl",
 }
@@ -87,10 +88,15 @@
         "libbinder_ndk",
         "libutils",
         "liblog",
+        "libstats_media_metrics",
+        "libstatspull",
+        "libstatssocket",
+        "libprotobuf-cpp-lite",
     ],
 
     static_libs: [
         "resourceobserver_aidl_interface-V1-ndk",
+        "libplatformprotos",
     ],
 
     include_dirs: ["frameworks/av/include"],
@@ -101,4 +107,10 @@
     ],
 
     export_include_dirs: ["."],
+
+    export_shared_lib_headers: [
+        "libstats_media_metrics",
+        "libstatspull",
+        "libstatssocket",
+    ],
 }
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index b4610bc..5582528 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -34,6 +34,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <unistd.h>
+#include <stats_media_metrics.h>
 
 #include "IMediaResourceMonitor.h"
 #include "ResourceManagerService.h"
@@ -42,6 +43,14 @@
 
 namespace android {
 
+using stats::media_metrics::stats_write;
+using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED;
+using stats::media_metrics::MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
+using stats::media_metrics::\
+    MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
+using stats::media_metrics::\
+    MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+
 //static
 std::mutex ResourceManagerService::sCookieLock;
 //static
@@ -97,7 +106,8 @@
 
     service->overridePid(mPid, -1);
     // thiz is freed in the call below, so it must be last call referring thiz
-    service->removeResource(mPid, mClientId, false /*checkValid*/);
+    ClientInfoParcel clientInfo{.pid = mPid, .id = mClientId};
+    service->removeResource(clientInfo, false /*checkValid*/);
 }
 
 class OverrideProcessInfoDeathNotifier : public DeathNotifier {
@@ -183,6 +193,7 @@
 }
 
 static ResourceInfo& getResourceInfoForEdit(uid_t uid, int64_t clientId,
+                                            const std::string& name,
         const std::shared_ptr<IResourceManagerClient>& client, ResourceInfos& infos) {
     ssize_t index = infos.indexOfKey(clientId);
 
@@ -190,6 +201,7 @@
         ResourceInfo info;
         info.uid = uid;
         info.clientId = clientId;
+        info.name = name;
         info.client = client;
         info.cookie = 0;
         info.pendingRemoval = false;
@@ -262,7 +274,15 @@
 
     result.append("  Processes:\n");
     for (size_t i = 0; i < mapCopy.size(); ++i) {
-        snprintf(buffer, SIZE, "    Pid: %d\n", mapCopy.keyAt(i));
+        int pid = mapCopy.keyAt(i);
+        snprintf(buffer, SIZE, "    Pid: %d\n", pid);
+        result.append(buffer);
+        int priority = 0;
+        if (getPriority_l(pid, &priority)) {
+            snprintf(buffer, SIZE, "    Priority: %d\n", priority);
+        } else {
+            snprintf(buffer, SIZE, "    Priority: <unknown>\n");
+        }
         result.append(buffer);
 
         const ResourceInfos &infos = mapCopy.valueAt(i);
@@ -271,10 +291,9 @@
             snprintf(buffer, SIZE, "        Id: %lld\n", (long long)infos[j].clientId);
             result.append(buffer);
 
-            std::string clientName;
-            Status status = infos[j].client->getName(&clientName);
-            if (!status.isOk()) {
-                clientName = "<unknown client>";
+            std::string clientName = "<unknown client>";
+            if (infos[j].client != nullptr) {
+                clientName = infos[j].name;
             }
             snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
             result.append(buffer);
@@ -344,7 +363,9 @@
     std::shared_ptr<ResourceManagerService> service =
             ::ndk::SharedRefBase::make<ResourceManagerService>();
     binder_status_t status =
-            AServiceManager_addService(service->asBinder().get(), getServiceName());
+            AServiceManager_addServiceWithFlags(
+                        service->asBinder().get(), getServiceName(),
+                        AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
     if (status != STATUS_OK) {
         return;
     }
@@ -434,11 +455,15 @@
     }
 }
 
-Status ResourceManagerService::addResource(int32_t pid, int32_t uid, int64_t clientId,
+Status ResourceManagerService::addResource(const ClientInfoParcel& clientInfo,
         const std::shared_ptr<IResourceManagerClient>& client,
         const std::vector<MediaResourceParcel>& resources) {
-    String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)",
-            pid, (long long) clientId, getString(resources).string());
+    int32_t pid = clientInfo.pid;
+    int32_t uid = clientInfo.uid;
+    int64_t clientId = clientInfo.id;
+    const std::string& name = clientInfo.name;
+    String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
+            pid, uid, (long long) clientId, getString(resources).string());
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
@@ -451,7 +476,7 @@
         uid = callingUid;
     }
     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
-    ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
+    ResourceInfo& info = getResourceInfoForEdit(uid, clientId, name, client, infos);
     ResourceList resourceAdded;
 
     for (size_t i = 0; i < resources.size(); ++i) {
@@ -490,13 +515,50 @@
         mObserverService->onResourceAdded(uid, pid, resourceAdded);
     }
     notifyResourceGranted(pid, resources);
+
+    // Increase the instance count of the resource associated with this client.
+    increaseResourceInstanceCount(clientId, name);
+
     return Status::ok();
 }
 
-Status ResourceManagerService::removeResource(int32_t pid, int64_t clientId,
+void ResourceManagerService::increaseResourceInstanceCount(int64_t clientId,
+                                                           const std::string& name) {
+    // Check whether this client has been looked into already.
+    if (mClientIdSet.find(clientId) == mClientIdSet.end()) {
+        mClientIdSet.insert(clientId);
+        // Update the resource instance count.
+        auto found = mConcurrentResourceCountMap.find(name);
+        if (found == mConcurrentResourceCountMap.end()) {
+            mConcurrentResourceCountMap[name] = 1;
+        } else {
+            found->second++;
+        }
+    }
+}
+
+void ResourceManagerService::decreaseResourceInstanceCount(int64_t clientId,
+                                                           const std::string& name) {
+    // Since this client has been removed, remove it from mClientIdSet
+    mClientIdSet.erase(clientId);
+    // Update the resource instance count also.
+    auto found = mConcurrentResourceCountMap.find(name);
+    if (found != mConcurrentResourceCountMap.end()) {
+        if (found->second == 1) {
+            mConcurrentResourceCountMap.erase(found);
+        } else {
+            found->second--;
+        }
+    }
+}
+
+Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources) {
-    String8 log = String8::format("removeResource(pid %d, clientId %lld, resources %s)",
-            pid, (long long) clientId, getString(resources).string());
+    int32_t pid = clientInfo.pid;
+    int32_t uid = clientInfo.uid;
+    int64_t clientId = clientInfo.id;
+    String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
+            pid, uid, (long long) clientId, getString(resources).string());
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
@@ -556,15 +618,17 @@
     return Status::ok();
 }
 
-Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
-    removeResource(pid, clientId, true /*checkValid*/);
+Status ResourceManagerService::removeClient(const ClientInfoParcel& clientInfo) {
+    removeResource(clientInfo, true /*checkValid*/);
     return Status::ok();
 }
 
-Status ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
-    String8 log = String8::format(
-            "removeResource(pid %d, clientId %lld)",
-            pid, (long long) clientId);
+Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo, bool checkValid) {
+    int32_t pid = clientInfo.pid;
+    int32_t uid = clientInfo.uid;
+    int64_t clientId = clientInfo.id;
+    String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
+            pid, uid, (long long) clientId);
     mServiceLog->add(log);
 
     Mutex::Autolock lock(mLock);
@@ -592,6 +656,10 @@
         onLastRemoved(it->second, info);
     }
 
+    // Since this client has been removed, decrease the corresponding
+    // resources instance count.
+    decreaseResourceInstanceCount(clientId, info.name);
+
     removeCookieAndUnlink_l(info.client, info.cookie);
 
     if (mObserverService != nullptr && !info.resources.empty()) {
@@ -602,25 +670,30 @@
     return Status::ok();
 }
 
-void ResourceManagerService::getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+void ResourceManagerService::getClientForResource_l(int callingPid,
+        const MediaResourceParcel *res,
+        PidUidVector* idVector,
         Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
     if (res == NULL) {
         return;
     }
     std::shared_ptr<IResourceManagerClient> client;
-    if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, &client)) {
+    if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, idVector, &client)) {
         clients->push_back(client);
     }
 }
 
-Status ResourceManagerService::reclaimResource(int32_t callingPid,
+Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
         const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
-    String8 log = String8::format("reclaimResource(callingPid %d, resources %s)",
-            callingPid, getString(resources).string());
+    int32_t callingPid = clientInfo.pid;
+    std::string clientName = clientInfo.name;
+    String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
+            callingPid, clientInfo.uid, getString(resources).string());
     mServiceLog->add(log);
     *_aidl_return = false;
 
     Vector<std::shared_ptr<IResourceManagerClient>> clients;
+    PidUidVector idVector;
     {
         Mutex::Autolock lock(mLock);
         if (!mProcessInfo->isPidTrusted(callingPid)) {
@@ -656,13 +729,13 @@
         if (secureCodec != NULL) {
             if (!mSupportsMultipleSecureCodecs) {
                 if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
-                            secureCodec->subType, &clients)) {
+                            secureCodec->subType, &idVector, &clients)) {
                     return Status::ok();
                 }
             }
             if (!mSupportsSecureWithNonSecureCodec) {
                 if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec,
-                            secureCodec->subType, &clients)) {
+                            secureCodec->subType, &idVector, &clients)) {
                     return Status::ok();
                 }
             }
@@ -670,13 +743,13 @@
         if (nonSecureCodec != NULL) {
             if (!mSupportsSecureWithNonSecureCodec) {
                 if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
-                        nonSecureCodec->subType, &clients)) {
+                        nonSecureCodec->subType, &idVector, &clients)) {
                     return Status::ok();
                 }
             }
         }
         if (drmSession != NULL) {
-            getClientForResource_l(callingPid, drmSession, &clients);
+            getClientForResource_l(callingPid, drmSession, &idVector, &clients);
             if (clients.size() == 0) {
                 return Status::ok();
             }
@@ -684,32 +757,108 @@
 
         if (clients.size() == 0) {
             // if no secure/non-secure codec conflict, run second pass to handle other resources.
-            getClientForResource_l(callingPid, graphicMemory, &clients);
+            getClientForResource_l(callingPid, graphicMemory, &idVector, &clients);
         }
 
         if (clients.size() == 0) {
             // if we are here, run the third pass to free one codec with the same type.
-            getClientForResource_l(callingPid, secureCodec, &clients);
-            getClientForResource_l(callingPid, nonSecureCodec, &clients);
+            getClientForResource_l(callingPid, secureCodec, &idVector, &clients);
+            getClientForResource_l(callingPid, nonSecureCodec, &idVector, &clients);
         }
 
         if (clients.size() == 0) {
             // if we are here, run the fourth pass to free one codec with the different type.
             if (secureCodec != NULL) {
                 MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
-                getClientForResource_l(callingPid, &temp, &clients);
+                getClientForResource_l(callingPid, &temp, &idVector, &clients);
             }
             if (nonSecureCodec != NULL) {
                 MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
-                getClientForResource_l(callingPid, &temp, &clients);
+                getClientForResource_l(callingPid, &temp, &idVector, &clients);
             }
         }
     }
 
     *_aidl_return = reclaimUnconditionallyFrom(clients);
+
+    // Log Reclaim Pushed Atom to statsd
+    pushReclaimAtom(clientInfo, clients, idVector, *_aidl_return);
+
     return Status::ok();
 }
 
+void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
+                        const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
+                        const PidUidVector& idVector, bool reclaimed) {
+    // Construct the metrics for codec reclaim as a pushed atom.
+    // 1. Information about the requester.
+    //  - UID and the priority (oom score)
+    int32_t callingPid = clientInfo.pid;
+    int32_t requesterUid = clientInfo.uid;
+    std::string clientName = clientInfo.name;
+    int requesterPriority = -1;
+    getPriority_l(callingPid, &requesterPriority);
+
+    //  2. Information about the codec.
+    //  - Name of the codec requested
+    //  - Number of concurrent codecs running.
+    int32_t noOfConcurrentCodecs = 0;
+    auto found = mConcurrentResourceCountMap.find(clientName);
+    if (found != mConcurrentResourceCountMap.end()) {
+        noOfConcurrentCodecs = found->second;
+    }
+
+    // 3. Information about the Reclaim:
+    // - Status of reclaim request
+    // - How many codecs are reclaimed
+    // - For each codecs reclaimed, information of the process that it belonged to:
+    //    - UID and the Priority (oom score)
+    int32_t reclaimStatus = MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_SUCCESS;
+    if (!reclaimed) {
+      if (clients.size() == 0) {
+        // No clients to reclaim from
+        reclaimStatus =
+            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_NO_CLIENTS;
+      } else {
+        // Couldn't reclaim resources from the clients
+        reclaimStatus =
+            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED__RECLAIM_STATUS__RECLAIM_FAILED_RECLAIM_RESOURCES;
+      }
+    }
+    int32_t noOfCodecsReclaimed = clients.size();
+    int32_t targetIndex = 1;
+    for (const auto& id : idVector) {
+        int32_t targetUid = id.second;
+        int targetPriority = -1;
+        getPriority_l(id.first, &targetPriority);
+        // Post the pushed atom
+        int result = stats_write(
+            MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED,
+            requesterUid,
+            requesterPriority,
+            clientName.c_str(),
+            noOfConcurrentCodecs,
+            reclaimStatus,
+            noOfCodecsReclaimed,
+            targetIndex,
+            targetUid,
+            targetPriority);
+        ALOGI("%s: Pushed MEDIA_CODEC_RECLAIM_REQUEST_COMPLETED atom: "
+              "Requester[pid(%d): uid(%d): priority(%d)] "
+              "Codec: [%s] "
+              "No of concurrent codecs: %d "
+              "Reclaim Status: %d "
+              "No of codecs reclaimed: %d "
+              "Target[%d][pid(%d): uid(%d): priority(%d)] "
+              "Atom Size: %d",
+              __func__, callingPid, requesterUid, requesterPriority,
+              clientName.c_str(), noOfConcurrentCodecs,
+              reclaimStatus, noOfCodecsReclaimed,
+              targetIndex, id.first, targetUid, targetPriority, result);
+        targetIndex++;
+    }
+}
+
 bool ResourceManagerService::reclaimUnconditionallyFrom(
         const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
     if (clients.size() == 0) {
@@ -869,7 +1018,9 @@
     mProcessInfoOverrideMap.erase(pid);
 }
 
-Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t clientId) {
+Status ResourceManagerService::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
+    int32_t pid = clientInfo.pid;
+    int64_t clientId = clientInfo.id;
     String8 log = String8::format(
             "markClientForPendingRemoval(pid %d, clientId %lld)",
             pid, (long long) clientId);
@@ -927,7 +1078,8 @@
                                                            MediaResource::SubType::kVideoCodec,
                                                            MediaResource::SubType::kImageCodec}) {
                         std::shared_ptr<IResourceManagerClient> client;
-                        if (getBiggestClientPendingRemoval_l(pid, type, subType, &client)) {
+                        uid_t uid = 0;
+                        if (getBiggestClientPendingRemoval_l(pid, type, subType, uid, &client)) {
                             clients.add(client);
                             continue;
                         }
@@ -936,8 +1088,9 @@
                 // Non-codec resources are shared by audio, video and image codecs (no subtype).
                 default:
                     std::shared_ptr<IResourceManagerClient> client;
+                    uid_t uid = 0;
                     if (getBiggestClientPendingRemoval_l(pid, type,
-                            MediaResource::SubType::kUnspecifiedSubType, &client)) {
+                            MediaResource::SubType::kUnspecifiedSubType, uid, &client)) {
                         clients.add(client);
                     }
                     break;
@@ -964,8 +1117,12 @@
 }
 
 bool ResourceManagerService::getAllClients_l(int callingPid, MediaResource::Type type,
-        MediaResource::SubType subType, Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
+        MediaResource::SubType subType,
+        PidUidVector* idVector,
+        Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
     Vector<std::shared_ptr<IResourceManagerClient>> temp;
+    PidUidVector tempIdList;
+
     for (size_t i = 0; i < mMap.size(); ++i) {
         ResourceInfos &infos = mMap.editValueAt(i);
         for (size_t j = 0; j < infos.size(); ++j) {
@@ -978,6 +1135,7 @@
                     return false;
                 }
                 temp.push_back(infos[j].client);
+                tempIdList.emplace_back(mMap.keyAt(i), infos[j].uid);
             }
         }
     }
@@ -986,19 +1144,24 @@
         return true;
     }
     clients->appendVector(temp);
+    idVector->insert(std::end(*idVector), std::begin(tempIdList), std::end(tempIdList));
     return true;
 }
 
 bool ResourceManagerService::getLowestPriorityBiggestClient_l(int callingPid,
-        MediaResource::Type type, MediaResource::SubType subType,
+        MediaResource::Type type,
+        MediaResource::SubType subType,
+        PidUidVector* idVector,
         std::shared_ptr<IResourceManagerClient> *client) {
     int lowestPriorityPid;
     int lowestPriority;
     int callingPriority;
+    uid_t uid = 0;
 
     // Before looking into other processes, check if we have clients marked for
     // pending removal in the same process.
-    if (getBiggestClientPendingRemoval_l(callingPid, type, subType, client)) {
+    if (getBiggestClientPendingRemoval_l(callingPid, type, subType, uid, client)) {
+        idVector->emplace_back(callingPid, uid);
         return true;
     }
     if (!getPriority_l(callingPid, &callingPriority)) {
@@ -1015,9 +1178,11 @@
         return false;
     }
 
-    if (!getBiggestClient_l(lowestPriorityPid, type, subType, client)) {
+    if (!getBiggestClient_l(lowestPriorityPid, type, subType, uid, client)) {
         return false;
     }
+
+    idVector->emplace_back(lowestPriorityPid, uid);
     return true;
 }
 
@@ -1069,12 +1234,14 @@
 }
 
 bool ResourceManagerService::getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
-        MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client) {
-    return getBiggestClient_l(pid, type, subType, client, true /* pendingRemovalOnly */);
+        MediaResource::SubType subType, uid_t& uid,
+        std::shared_ptr<IResourceManagerClient> *client) {
+    return getBiggestClient_l(pid, type, subType, uid, client, true /* pendingRemovalOnly */);
 }
 
 bool ResourceManagerService::getBiggestClient_l(int pid, MediaResource::Type type,
-        MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client,
+        MediaResource::SubType subType, uid_t& uid,
+        std::shared_ptr<IResourceManagerClient> *client,
         bool pendingRemovalOnly) {
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
@@ -1097,6 +1264,7 @@
                 if (resource.value > largestValue) {
                     largestValue = resource.value;
                     clientTemp = infos[i].client;
+                    uid = infos[i].uid;
                 }
             }
         }
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index c636a0f..0016a19 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -19,7 +19,9 @@
 #define ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
 
 #include <map>
+#include <set>
 #include <mutex>
+#include <string>
 
 #include <aidl/android/media/BnResourceManagerService.h>
 #include <arpa/inet.h>
@@ -43,20 +45,24 @@
 using ::aidl::android::media::BnResourceManagerService;
 using ::aidl::android::media::MediaResourceParcel;
 using ::aidl::android::media::MediaResourcePolicyParcel;
+using ::aidl::android::media::ClientInfoParcel;
 
 typedef std::map<std::tuple<
         MediaResource::Type, MediaResource::SubType, std::vector<uint8_t>>,
         MediaResourceParcel> ResourceList;
 
 struct ResourceInfo {
-    int64_t clientId;
     uid_t uid;
+    int64_t clientId;
+    std::string name;
     std::shared_ptr<IResourceManagerClient> client;
     uintptr_t cookie{0};
     ResourceList resources;
     bool pendingRemoval{false};
 };
 
+typedef std::vector<std::pair<int32_t, uid_t>> PidUidVector;
+
 // TODO: convert these to std::map
 typedef KeyedVector<int64_t, ResourceInfo> ResourceInfos;
 typedef KeyedVector<int, ResourceInfos> PidResourceInfosMap;
@@ -85,31 +91,32 @@
     // IResourceManagerService interface
     Status config(const std::vector<MediaResourcePolicyParcel>& policies) override;
 
-    Status addResource(int32_t pid, int32_t uid, int64_t clientId,
-            const std::shared_ptr<IResourceManagerClient>& client,
-            const std::vector<MediaResourceParcel>& resources) override;
+    Status addResource(const ClientInfoParcel& clientInfo,
+                       const std::shared_ptr<IResourceManagerClient>& client,
+                       const std::vector<MediaResourceParcel>& resources) override;
 
-    Status removeResource(int32_t pid, int64_t clientId,
-            const std::vector<MediaResourceParcel>& resources) override;
+    Status removeResource(const ClientInfoParcel& clientInfo,
+                          const std::vector<MediaResourceParcel>& resources) override;
 
-    Status removeClient(int32_t pid, int64_t clientId) override;
+    Status removeClient(const ClientInfoParcel& clientInfo) override;
 
     // Tries to reclaim resource from processes with lower priority than the calling process
     // according to the requested resources.
     // Returns true if any resource has been reclaimed, otherwise returns false.
-    Status reclaimResource(int32_t callingPid, const std::vector<MediaResourceParcel>& resources,
-            bool* _aidl_return) override;
+    Status reclaimResource(const ClientInfoParcel& clientInfo,
+                           const std::vector<MediaResourceParcel>& resources,
+                           bool* _aidl_return) override;
 
-    Status overridePid(int originalPid, int newPid) override;
+    Status overridePid(int32_t originalPid, int32_t newPid) override;
 
-    Status overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client, int pid,
-            int procState, int oomScore) override;
+    Status overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client,
+                               int32_t pid, int32_t procState, int32_t oomScore) override;
 
-    Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
+    Status markClientForPendingRemoval(const ClientInfoParcel& clientInfo) override;
 
     Status reclaimResourcesFromClientsPendingRemoval(int32_t pid) override;
 
-    Status removeResource(int pid, int64_t clientId, bool checkValid);
+    Status removeResource(const ClientInfoParcel& clientInfo, bool checkValid);
 
 private:
     friend class ResourceManagerServiceTest;
@@ -124,13 +131,15 @@
     // Returns false if any client belongs to a process with higher priority than the
     // calling process. The clients will remain unchanged if returns false.
     bool getAllClients_l(int callingPid, MediaResource::Type type, MediaResource::SubType subType,
+            PidUidVector* idList,
             Vector<std::shared_ptr<IResourceManagerClient>> *clients);
 
     // Gets the client who owns specified resource type from lowest possible priority process.
     // Returns false if the calling process priority is not higher than the lowest process
     // priority. The client will remain unchanged if returns false.
     bool getLowestPriorityBiggestClient_l(int callingPid, MediaResource::Type type,
-            MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client);
+            MediaResource::SubType subType, PidUidVector* idList,
+            std::shared_ptr<IResourceManagerClient> *client);
 
     // Gets lowest priority process that has the specified resource type.
     // Returns false if failed. The output parameters will remain unchanged if failed.
@@ -141,17 +150,19 @@
     // Returns false with no change to client if there are no clients holdiing resources of thisi
     // type.
     bool getBiggestClient_l(int pid, MediaResource::Type type, MediaResource::SubType subType,
-            std::shared_ptr<IResourceManagerClient> *client,
+            uid_t& uid, std::shared_ptr<IResourceManagerClient> *client,
             bool pendingRemovalOnly = false);
     // Same method as above, but with pendingRemovalOnly as true.
     bool getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
-            MediaResource::SubType subType, std::shared_ptr<IResourceManagerClient> *client);
+            MediaResource::SubType subType, uid_t& uid,
+            std::shared_ptr<IResourceManagerClient> *client);
 
     bool isCallingPriorityHigher_l(int callingPid, int pid);
 
     // A helper function basically calls getLowestPriorityBiggestClient_l and add
     // the result client to the given Vector.
     void getClientForResource_l(int callingPid, const MediaResourceParcel *res,
+            PidUidVector* idList,
             Vector<std::shared_ptr<IResourceManagerClient>> *clients);
 
     void onFirstAdded(const MediaResourceParcel& res, const ResourceInfo& clientInfo);
@@ -171,6 +182,15 @@
     void removeCookieAndUnlink_l(const std::shared_ptr<IResourceManagerClient>& client,
                                  uintptr_t cookie);
 
+    // To increase/decrease the number of instances of a given resource
+    // associated with a client.
+    void increaseResourceInstanceCount(int64_t clientId, const std::string& name);
+    void decreaseResourceInstanceCount(int64_t clientId, const std::string& name);
+
+    void pushReclaimAtom(const ClientInfoParcel& clientInfo,
+                         const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
+                         const PidUidVector& idList, bool reclaimed);
+
     mutable Mutex mLock;
     sp<ProcessInfoInterface> mProcessInfo;
     sp<SystemCallbackInterface> mSystemCB;
@@ -191,6 +211,11 @@
     static std::map<uintptr_t, sp<DeathNotifier> > sCookieToDeathNotifierMap
             GUARDED_BY(sCookieLock);
     std::shared_ptr<ResourceObserverService> mObserverService;
+
+    // List of active clients
+    std::set<int64_t> mClientIdSet;
+    // Map of resources (name) and number of concurrent instances
+    std::map<std::string, int> mConcurrentResourceCountMap;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/mediaresourcemanager/ResourceObserverService.cpp b/services/mediaresourcemanager/ResourceObserverService.cpp
index 4e97406..ebe3903 100644
--- a/services/mediaresourcemanager/ResourceObserverService.cpp
+++ b/services/mediaresourcemanager/ResourceObserverService.cpp
@@ -100,8 +100,10 @@
 std::shared_ptr<ResourceObserverService> ResourceObserverService::instantiate() {
     std::shared_ptr<ResourceObserverService> observerService =
             ::ndk::SharedRefBase::make<ResourceObserverService>();
-    binder_status_t status = AServiceManager_addService(observerService->asBinder().get(),
-            ResourceObserverService::getServiceName());
+    binder_status_t status = AServiceManager_addServiceWithFlags(
+      observerService->asBinder().get(),ResourceObserverService::getServiceName(),
+      AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
+
     if (status != STATUS_OK) {
         return nullptr;
     }
diff --git a/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
new file mode 100644
index 0000000..eb4bc42
--- /dev/null
+++ b/services/mediaresourcemanager/aidl/android/media/ClientInfoParcel.aidl
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+/**
+ * Description of a Client(codec) information.
+ *
+ * {@hide}
+ */
+parcelable ClientInfoParcel {
+    /**
+     * The PID of the client process.
+     */
+    int pid = -1;
+
+    /**
+     * The UID of the client process.
+     */
+    int uid = -1;
+
+    /**
+     * The ID of the client.
+     */
+    long id = 0;
+
+    /**
+     * Name of the resource associated with the client.
+     */
+    @utf8InCpp String name;
+}
diff --git a/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl b/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
index 7a0a50f..30ad41b 100644
--- a/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
+++ b/services/mediaresourcemanager/aidl/android/media/IResourceManagerService.aidl
@@ -19,6 +19,7 @@
 import android.media.IResourceManagerClient;
 import android.media.MediaResourceParcel;
 import android.media.MediaResourcePolicyParcel;
+import android.media.ClientInfoParcel;
 
 /**
  * ResourceManagerService interface that keeps track of media resource
@@ -44,46 +45,40 @@
     /**
      * Add a client to a process with a list of resources.
      *
-     * @param pid pid of the client.
-     * @param uid uid of the client.
-     * @param clientId an identifier that uniquely identifies the client within the pid.
+     * @param clientInfo info of the calling client.
      * @param client interface for the ResourceManagerService to call the client.
      * @param resources an array of resources to be added.
      */
     void addResource(
-            int pid,
-            int uid,
-            long clientId,
+            in ClientInfoParcel clientInfo,
             IResourceManagerClient client,
             in MediaResourceParcel[] resources);
 
     /**
      * Remove the listed resources from a client.
      *
-     * @param pid pid from which the list of resources will be removed.
-     * @param clientId clientId within the pid from which the list of resources will be removed.
+     * @param clientInfo info of the calling client.
      * @param resources an array of resources to be removed from the client.
      */
-    void removeResource(int pid, long clientId, in MediaResourceParcel[] resources);
+    void removeResource(in ClientInfoParcel clientInfo, in MediaResourceParcel[] resources);
 
     /**
      * Remove all resources from a client.
      *
-     * @param pid pid from which the client's resources will be removed.
-     * @param clientId clientId within the pid that will be removed.
+     * @param clientInfo info of the calling client.
      */
-    void removeClient(int pid, long clientId);
+    void removeClient(in ClientInfoParcel clientInfo);
 
     /**
      * Tries to reclaim resource from processes with lower priority than the
      * calling process according to the requested resources.
      *
-     * @param callingPid pid of the calling process.
+     * @param clientInfo info of the calling client.
      * @param resources an array of resources to be reclaimed.
      *
      * @return true if the reclaim was successful and false otherwise.
      */
-    boolean reclaimResource(int callingPid, in MediaResourceParcel[] resources);
+    boolean reclaimResource(in ClientInfoParcel clientInfo, in MediaResourceParcel[] resources);
 
     /**
      * Override the pid of original calling process with the pid of the process
@@ -120,10 +115,9 @@
     /**
      * Mark a client for pending removal
      *
-     * @param pid pid from which the client's resources will be removed.
-     * @param clientId clientId within the pid that will be removed.
+     * @param clientInfo info of the calling client.
      */
-    void markClientForPendingRemoval(int pid, long clientId);
+    void markClientForPendingRemoval(in ClientInfoParcel clientInfo);
 
     /**
      * Reclaim resources from clients pending removal, if any.
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index 81c85e5..1d7f14f 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -41,6 +41,9 @@
         "libbinder_ndk",
         "libmedia",
         "libutils",
+        "libstats_media_metrics",
+        "libstatspull",
+        "libstatssocket",
     ],
     fuzz_config: {
         cc: [
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
index e4aaea0..5c2fef9 100644
--- a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -135,11 +135,15 @@
 };
 
 struct TestClient : public BnResourceManagerClient {
-    TestClient(int pid, const shared_ptr<ResourceManagerService>& service)
-        : mReclaimed(false), mPid(pid), mService(service) {}
+    TestClient(int pid, int uid, const shared_ptr<ResourceManagerService>& service)
+        : mReclaimed(false), mPid(pid), mUid(uid), mService(service) {}
 
     Status reclaimResource(bool* aidlReturn) override {
-        mService->removeClient(mPid, getId(ref<TestClient>()));
+        ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                    .uid = static_cast<int32_t>(mUid),
+                                    .id = getId(ref<TestClient>()),
+                                    .name = ""};
+        mService->removeClient(clientInfo);
         mReclaimed = true;
         *aidlReturn = true;
         return Status::ok();
@@ -155,6 +159,7 @@
    private:
     bool mReclaimed;
     int mPid;
+    int mUid;
     shared_ptr<ResourceManagerService> mService;
     DISALLOW_EVIL_CONSTRUCTORS(TestClient);
 };
@@ -176,9 +181,12 @@
     static void* addResource(void* arg) {
         resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
         if (tArgs) {
+            ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(tArgs->pid),
+                                        .uid = static_cast<int32_t>(tArgs->uid),
+                                        .id = tArgs->testClientId,
+                                        .name = ""};
             (tArgs->service)
-                ->addResource(tArgs->pid, tArgs->uid, tArgs->testClientId, tArgs->testClient,
-                              tArgs->mediaResource);
+                ->addResource(clientInfo, tArgs->testClient, tArgs->mediaResource);
         }
         return nullptr;
     }
@@ -187,10 +195,14 @@
         resourceThreadArgs* tArgs = (resourceThreadArgs*)arg;
         if (tArgs) {
             bool result;
-            (tArgs->service)->markClientForPendingRemoval(tArgs->pid, tArgs->testClientId);
-            (tArgs->service)->removeResource(tArgs->pid, tArgs->testClientId, tArgs->mediaResource);
-            (tArgs->service)->reclaimResource(tArgs->pid, tArgs->mediaResource, &result);
-            (tArgs->service)->removeClient(tArgs->pid, tArgs->testClientId);
+            ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(tArgs->pid),
+                                        .uid = static_cast<int32_t>(tArgs->uid),
+                                        .id = tArgs->testClientId,
+                                        .name = ""};
+            (tArgs->service)->markClientForPendingRemoval(clientInfo);
+            (tArgs->service)->removeResource(clientInfo, tArgs->mediaResource);
+            (tArgs->service)->reclaimResource(clientInfo, tArgs->mediaResource, &result);
+            (tArgs->service)->removeClient(clientInfo);
             (tArgs->service)->overridePid(tArgs->pid, tArgs->pid - 1);
         }
         return nullptr;
@@ -240,7 +252,8 @@
         uint64_t mediaResourceValue = mFuzzedDataProvider->ConsumeIntegral<uint64_t>();
         threadArgs[k].service = mService;
         shared_ptr<IResourceManagerClient> testClient =
-                ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, mService);
+                ::ndk::SharedRefBase::make<TestClient>(threadArgs[k].pid, threadArgs[k].uid,
+                                                       mService);
         threadArgs[k].testClient = testClient;
         threadArgs[k].testClientId = getId(testClient);
         mediaResource[k].push_back(MediaResource(static_cast<MedResType>(mediaResourceType),
@@ -258,7 +271,7 @@
     // No resource was added with pid = 0
     int32_t pidZero = 0;
     shared_ptr<IResourceManagerClient> testClient =
-        ::ndk::SharedRefBase::make<TestClient>(pidZero, mService);
+        ::ndk::SharedRefBase::make<TestClient>(pidZero, 0, mService);
     int32_t mediaResourceType =
         mFuzzedDataProvider->ConsumeIntegralInRange<int32_t>(kMinResourceType, kMaxResourceType);
     int32_t mediaResourceSubType =
@@ -269,9 +282,13 @@
                                      static_cast<MedResSubType>(mediaResourceSubType),
                                      mediaResourceValue));
     bool result;
-    mService->reclaimResource(pidZero, mediaRes, &result);
-    mService->removeResource(pidZero, getId(testClient), mediaRes);
-    mService->removeClient(pidZero, getId(testClient));
+    ClientInfoParcel pidZeroClient{.pid = static_cast<int32_t>(pidZero),
+                                   .uid = static_cast<int32_t>(0),
+                                   .id = getId(testClient),
+                                   .name = ""};
+    mService->reclaimResource(pidZeroClient, mediaRes, &result);
+    mService->removeResource(pidZeroClient, mediaRes);
+    mService->removeClient(pidZeroClient);
 }
 
 void ResourceManagerServiceFuzzer::setServiceLog() {
diff --git a/services/mediaresourcemanager/test/Android.bp b/services/mediaresourcemanager/test/Android.bp
index 618626f..60bb8c3 100644
--- a/services/mediaresourcemanager/test/Android.bp
+++ b/services/mediaresourcemanager/test/Android.bp
@@ -19,6 +19,9 @@
         "liblog",
         "libmedia",
         "libutils",
+        "libstats_media_metrics",
+        "libstatspull",
+        "libstatssocket",
     ],
     include_dirs: [
         "frameworks/av/include",
@@ -64,6 +67,9 @@
         "liblog",
         "libmedia",
         "libutils",
+        "libstats_media_metrics",
+        "libstatspull",
+        "libstatssocket",
     ],
     include_dirs: [
         "frameworks/av/include",
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 5bf44ce..8194e23 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -122,11 +122,15 @@
 
 
 struct TestClient : public BnResourceManagerClient {
-    TestClient(int pid, const std::shared_ptr<ResourceManagerService> &service)
-        : mPid(pid), mService(service) {}
+    TestClient(int pid, int uid, const std::shared_ptr<ResourceManagerService> &service)
+        : mPid(pid), mUid(uid), mService(service) {}
 
     Status reclaimResource(bool* _aidl_return) override {
-        mService->removeClient(mPid, getId(ref<TestClient>()));
+        ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
+                                    .uid = static_cast<int32_t>(mUid),
+                                    .id = getId(ref<TestClient>()),
+                                    .name = "none"};
+        mService->removeClient(clientInfo);
         mWasReclaimResourceCalled = true;
         *_aidl_return = true;
         return Status::ok();
@@ -148,6 +152,7 @@
 private:
     bool mWasReclaimResourceCalled = false;
     int mPid;
+    int mUid;
     std::shared_ptr<ResourceManagerService> mService;
     DISALLOW_EVIL_CONSTRUCTORS(TestClient);
 };
@@ -196,13 +201,13 @@
         : mSystemCB(new TestSystemCallback()),
           mService(::ndk::SharedRefBase::make<ResourceManagerService>(
                   new TestProcessInfo, mSystemCB)),
-          mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, mService)),
-          mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)),
-          mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, mService)) {
+          mTestClient1(::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, mService)),
+          mTestClient2(::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService)),
+          mTestClient3(::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, mService)) {
     }
 
-    std::shared_ptr<IResourceManagerClient> createTestClient(int pid) {
-        return ::ndk::SharedRefBase::make<TestClient>(pid, mService);
+    std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid) {
+        return ::ndk::SharedRefBase::make<TestClient>(pid, uid, mService);
     }
 
     sp<TestSystemCallback> mSystemCB;
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 8739c3b..41cccb8 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -98,24 +98,36 @@
         // kTestPid1 mTestClient1
         std::vector<MediaResourceParcel> resources1;
         resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        mService->addResource(client1Info, mTestClient1, resources1);
         resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
         std::vector<MediaResourceParcel> resources11;
         resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+        mService->addResource(client1Info, mTestClient1, resources11);
 
         // kTestPid2 mTestClient2
         std::vector<MediaResourceParcel> resources2;
         resources2.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
         resources2.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
-        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient2),
+                                     .name = "none"};
+        mService->addResource(client2Info, mTestClient2, resources2);
 
         // kTestPid2 mTestClient3
         std::vector<MediaResourceParcel> resources3;
-        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
+        ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient3),
+                                     .name = "none"};
+        mService->addResource(client3Info, mTestClient3, resources3);
         resources3.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
         resources3.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
-        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
+        mService->addResource(client3Info, mTestClient3, resources3);
 
         const PidResourceInfosMap &map = mService->mMap;
         EXPECT_EQ(2u, map.size());
@@ -138,7 +150,11 @@
         std::vector<MediaResourceParcel> resources1;
         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -100));
         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -100));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         // Expected result:
         // 1) the client should have been added;
@@ -155,11 +171,11 @@
         resources1.clear();
         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
         resources1.clear();
         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, 10));
         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 10));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         // Expected result:
         // Both values should saturate to INT64_MAX
@@ -170,7 +186,7 @@
         resources1.clear();
         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -10));
         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -10));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         // Expected result:
         // 1) DrmSession resource should allow negative value addition, and value should drop accordingly
@@ -182,7 +198,7 @@
         resources1.clear();
         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MIN));
         expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MIN));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         // Expected result:
         // 1) DrmSession resource value should drop to 0, but the entry shouldn't be removed.
@@ -228,11 +244,15 @@
         // kTestPid1 mTestClient1
         std::vector<MediaResourceParcel> resources1;
         resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         std::vector<MediaResourceParcel> resources11;
         resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+        mService->addResource(client1Info, mTestClient1, resources11);
 
         const PidResourceInfosMap &map = mService->mMap;
         EXPECT_EQ(1u, map.size());
@@ -243,7 +263,7 @@
 
         // test adding existing types to combine values
         resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         std::vector<MediaResourceParcel> expected;
         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
@@ -253,7 +273,7 @@
         // test adding new types (including types that differs only in subType)
         resources11.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
         resources11.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+        mService->addResource(client1Info, mTestClient1, resources11);
 
         expected.clear();
         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
@@ -267,11 +287,15 @@
         // kTestPid1 mTestClient1
         std::vector<MediaResourceParcel> resources1;
         resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        mService->addResource(client1Info, mTestClient1, resources1);
 
         std::vector<MediaResourceParcel> resources11;
         resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
+        mService->addResource(client1Info, mTestClient1, resources11);
 
         const PidResourceInfosMap &map = mService->mMap;
         EXPECT_EQ(1u, map.size());
@@ -282,7 +306,7 @@
 
         // test partial removal
         resources11[0].value = 100;
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+        mService->removeResource(client1Info, resources11);
 
         std::vector<MediaResourceParcel> expected;
         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -291,13 +315,13 @@
 
         // test removal request with negative value, should be ignored
         resources11[0].value = -10000;
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+        mService->removeResource(client1Info, resources11);
 
         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
 
         // test complete removal with overshoot value
         resources11[0].value = 1000;
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
+        mService->removeResource(client1Info, resources11);
 
         expected.clear();
         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
@@ -317,19 +341,35 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low to reclaim resource
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                        .uid = static_cast<int32_t>(kTestUid1),
+                                        .id = 0,
+                                        .name = "none"};
+            CHECK_STATUS_FALSE(mService->reclaimResource(clientInfo, resources, &result));
 
             // override Low Priority Pid with High Priority Pid
             mService->overridePid(kLowPriorityPid, kHighPriorityPid);
-            CHECK_STATUS_TRUE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(clientInfo, resources, &result));
 
             // restore Low Priority Pid
             mService->overridePid(kLowPriorityPid, -1);
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(clientInfo, resources, &result));
         }
     }
 
     void testMarkClientForPendingRemoval() {
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient2),
+                                     .name = "none"};
+        ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient3),
+                                     .name = "none"};
         {
             addResource();
             mService->mSupportsSecureWithNonSecureCodec = true;
@@ -338,24 +378,24 @@
             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
 
             // Remove low priority clients
-            mService->removeClient(kTestPid1, getId(mTestClient1));
+            mService->removeClient(client1Info);
 
             // no lower priority client
-            CHECK_STATUS_FALSE(mService->reclaimResource(kTestPid2, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(client2Info, resources, &result));
             EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
-            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+            mService->markClientForPendingRemoval(client2Info);
 
             // client marked for pending removal from the same process got reclaimed
-            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
             EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_EQ(true, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // clean up client 3 which still left
-            mService->removeClient(kTestPid2, getId(mTestClient3));
+            mService->removeClient(client3Info);
         }
 
         {
@@ -365,30 +405,30 @@
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
 
-            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+            mService->markClientForPendingRemoval(client2Info);
 
             // client marked for pending removal from the same process got reclaimed
             // first, even though there are lower priority process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
             EXPECT_EQ(false, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_EQ(true, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // lower priority client got reclaimed
-            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(client2Info, resources, &result));
             EXPECT_EQ(true, toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // clean up client 3 which still left
-            mService->removeClient(kTestPid2, getId(mTestClient3));
+            mService->removeClient(client3Info);
         }
 
         {
             addResource();
             mService->mSupportsSecureWithNonSecureCodec = true;
 
-            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
+            mService->markClientForPendingRemoval(client2Info);
 
             // client marked for pending removal got reclaimed
             EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
@@ -402,7 +442,7 @@
             EXPECT_EQ(false, toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_EQ(false, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
-            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));
+            mService->markClientForPendingRemoval(client3Info);
 
             // client marked for pending removal got reclaimed
             EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
@@ -411,14 +451,18 @@
             EXPECT_EQ(true, toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // clean up client 1 which still left
-            mService->removeClient(kTestPid1, getId(mTestClient1));
+            mService->removeClient(client1Info);
         }
     }
 
     void testRemoveClient() {
         addResource();
 
-        mService->removeClient(kTestPid2, getId(mTestClient2));
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient2),
+                                     .name = "none"};
+        mService->removeClient(client2Info);
 
         const PidResourceInfosMap &map = mService->mMap;
         EXPECT_EQ(2u, map.size());
@@ -437,11 +481,12 @@
         MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
 
         Vector<std::shared_ptr<IResourceManagerClient> > clients;
-        EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, subType, &clients));
+        PidUidVector idList;
+        EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, subType, &idList, &clients));
         // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
         // will fail.
-        EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, subType, &clients));
-        EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, subType, &clients));
+        EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, subType, &idList, &clients));
+        EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, subType, &idList, &clients));
 
         EXPECT_EQ(2u, clients.size());
         // (OK to require ordering in clients[], as the pid map is sorted)
@@ -454,6 +499,19 @@
         resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
         resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
 
+        ClientInfoParcel lowPriorityClient{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                          .uid = static_cast<int32_t>(kTestUid2),
+                                           .id = 0,
+                                           .name = "none"};
+        ClientInfoParcel midPriorityClient{.pid = static_cast<int32_t>(kMidPriorityPid),
+                                           .uid = static_cast<int32_t>(kTestUid2),
+                                           .id = 0,
+                                           .name = "none"};
+        ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+                                            .uid = static_cast<int32_t>(kTestUid2),
+                                            .id = 0,
+                                            .name = "none"};
+
         // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
         {
             addResource();
@@ -461,23 +519,23 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
-            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
 
             // reclaim all secure codecs
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim one largest graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // nothing left
-            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
         }
 
         // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
@@ -487,17 +545,17 @@
             mService->mSupportsSecureWithNonSecureCodec = false;
 
             // priority too low
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
-            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
 
             // reclaim all secure and non-secure codecs
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // nothing left
-            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
         }
 
 
@@ -508,29 +566,29 @@
             mService->mSupportsSecureWithNonSecureCodec = false;
 
             // priority too low
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
-            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
 
             // reclaim all non-secure codecs
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim one largest graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim another largest graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // nothing left
-            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
         }
 
         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -540,28 +598,28 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
 
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             // one largest graphic memory from lowest process got reclaimed
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim another graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim another graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // nothing left
-            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
         }
 
         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
@@ -573,20 +631,20 @@
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
 
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             // secure codec from lowest process got reclaimed
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim another secure codec from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // no more secure codec, non-secure codec will be reclaimed.
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
@@ -598,29 +656,42 @@
         resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
         resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
 
+        ClientInfoParcel lowPriorityClient{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                          .uid = static_cast<int32_t>(kTestUid2),
+                                           .id = 0,
+                                           .name = "none"};
+        ClientInfoParcel midPriorityClient{.pid = static_cast<int32_t>(kMidPriorityPid),
+                                           .uid = static_cast<int32_t>(kTestUid2),
+                                           .id = 0,
+                                           .name = "none"};
+        ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+                                            .uid = static_cast<int32_t>(kTestUid2),
+                                            .id = 0,
+                                            .name = "none"};
+
         // ### secure codec can't coexist with non-secure codec ###
         {
             addResource();
             mService->mSupportsSecureWithNonSecureCodec = false;
 
             // priority too low
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
-            CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(midPriorityClient, resources, &result));
 
             // reclaim all secure codecs
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim one graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // nothing left
-            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
         }
 
 
@@ -630,28 +701,28 @@
             mService->mSupportsSecureWithNonSecureCodec = true;
 
             // priority too low
-            CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(lowPriorityClient, resources, &result));
 
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             // one largest graphic memory from lowest process got reclaimed
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim another graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // call again should reclaim another graphic memory from lowest process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // nothing left
-            CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, resources, &result));
         }
 
         // ### secure codec can coexist with non-secure codec ###
@@ -662,20 +733,24 @@
             std::vector<MediaResourceParcel> resources;
             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
 
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             // one non secure codec from lowest process got reclaimed
             EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_TRUE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // no more non-secure codec, secure codec from lowest priority process will be reclaimed
-            CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
+            CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, resources, &result));
             EXPECT_TRUE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient2)->checkIfReclaimedAndReset());
             EXPECT_FALSE(toTestClient(mTestClient3)->checkIfReclaimedAndReset());
 
             // clean up client 3 which still left
-            mService->removeClient(kTestPid2, getId(mTestClient3));
+            ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(kTestPid2),
+                                        .uid = static_cast<int32_t>(kTestUid2),
+                                        .id = getId(mTestClient3),
+                                        .name = "none"};
+            mService->removeClient(clientInfo);
         }
     }
 
@@ -683,15 +758,16 @@
         MediaResource::Type type = MediaResource::Type::kGraphicMemory;
         MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
         std::shared_ptr<IResourceManagerClient> client;
+        PidUidVector idList;
         EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, subType,
-                &client));
+                &idList, &client));
 
         addResource();
 
         EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, subType,
-                &client));
+                &idList, &client));
         EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, subType,
-                &client));
+                &idList, &client));
 
         // kTestPid1 is the lowest priority process with MediaResource::Type::kGraphicMemory.
         // mTestClient1 has the largest MediaResource::Type::kGraphicMemory within kTestPid1.
@@ -737,33 +813,41 @@
         // new client request should cause VIDEO_ON
         std::vector<MediaResourceParcel> resources1;
         resources1.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 1));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        mService->addResource(client1Info, mTestClient1, resources1);
         EXPECT_EQ(2u, mSystemCB->eventCount());
         EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
 
         // each client should only cause 1 VIDEO_ON
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
         EXPECT_EQ(2u, mSystemCB->eventCount());
 
         // new client request should cause VIDEO_ON
         std::vector<MediaResourceParcel> resources2;
         resources2.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 2));
-        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient2),
+                                     .name = "none"};
+        mService->addResource(client2Info, mTestClient2, resources2);
         EXPECT_EQ(3u, mSystemCB->eventCount());
         EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
 
         // partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
+        mService->removeResource(client1Info, resources1);
         EXPECT_EQ(3u, mSystemCB->eventCount());
 
         // remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
         // (use resource2 to test removing more instances than previously requested)
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
+        mService->removeResource(client1Info, resources2);
         EXPECT_EQ(4u, mSystemCB->eventCount());
         EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());
 
         // remove mTestClient2, should be VIDEO_OFF for kTestUid2
-        mService->removeClient(kTestPid2, getId(mTestClient2));
+        mService->removeClient(client2Info);
         EXPECT_EQ(5u, mSystemCB->eventCount());
         EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
     }
@@ -776,32 +860,40 @@
         // new client request should cause CPUSET_ENABLE
         std::vector<MediaResourceParcel> resources1;
         resources1.push_back(MediaResource(MediaResource::Type::kCpuBoost, 1));
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(mTestClient1),
+                                     .name = "none"};
+        mService->addResource(client1Info, mTestClient1, resources1);
         EXPECT_EQ(2u, mSystemCB->eventCount());
         EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
 
         // each client should only cause 1 CPUSET_ENABLE
-        mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
+        mService->addResource(client1Info, mTestClient1, resources1);
         EXPECT_EQ(2u, mSystemCB->eventCount());
 
         // new client request should cause CPUSET_ENABLE
         std::vector<MediaResourceParcel> resources2;
         resources2.push_back(MediaResource(MediaResource::Type::kCpuBoost, 2));
-        mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(mTestClient2),
+                                     .name = "none"};
+        mService->addResource(client2Info, mTestClient2, resources2);
         EXPECT_EQ(3u, mSystemCB->eventCount());
         EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
 
         // remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
-        mService->removeClient(kTestPid2, getId(mTestClient2));
+        mService->removeClient(client2Info);
         EXPECT_EQ(3u, mSystemCB->eventCount());
 
         // remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
+        mService->removeResource(client1Info, resources1);
         EXPECT_EQ(3u, mSystemCB->eventCount());
 
         // remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
         // (use resource2 to test removing more than previously requested)
-        mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
+        mService->removeResource(client1Info, resources2);
         EXPECT_EQ(4u, mSystemCB->eventCount());
         EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
     }
@@ -814,22 +906,32 @@
         std::vector<MediaResourceParcel> audioImageResources;
         audioImageResources.push_back(createNonSecureAudioCodecResource());
         audioImageResources.push_back(createNonSecureImageCodecResource());
-        mService->addResource(kLowPriorityPid, kTestUid1, getId(audioImageTestClient),
-                audioImageTestClient, audioImageResources);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(audioImageTestClient),
+                                     .name = "none"};
+        mService->addResource(client1Info, audioImageTestClient, audioImageResources);
 
         // Fail to reclaim a video codec resource
         std::vector<MediaResourceParcel> reclaimResources;
         reclaimResources.push_back(createNonSecureVideoCodecResource());
-        CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+                                            .uid = static_cast<int32_t>(kTestUid2),
+                                            .id = 0,
+                                            .name = "none"};
+        CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Now add a video codec resource
         std::vector<MediaResourceParcel> videoResources;
         videoResources.push_back(createNonSecureVideoCodecResource());
-        mService->addResource(kLowPriorityPid, kTestUid1, getId(videoTestClient), videoTestClient,
-                videoResources);
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(videoTestClient),
+                                     .name = "none"};
+        mService->addResource(client2Info, videoTestClient, videoResources);
 
         // Verify that the newly-created video codec resource can be reclaimed
-        CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Verify that the audio and image resources are untouched
         EXPECT_FALSE(toTestClient(audioImageTestClient)->checkIfReclaimedAndReset());
@@ -845,22 +947,32 @@
         std::vector<MediaResourceParcel> videoImageResources;
         videoImageResources.push_back(createNonSecureVideoCodecResource());
         videoImageResources.push_back(createNonSecureImageCodecResource());
-        mService->addResource(kLowPriorityPid, kTestUid1, getId(videoImageTestClient),
-                videoImageTestClient, videoImageResources);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(videoImageTestClient),
+                                     .name = "none"};
+        mService->addResource(client1Info, videoImageTestClient, videoImageResources);
 
         // Fail to reclaim an audio codec resource
         std::vector<MediaResourceParcel> reclaimResources;
         reclaimResources.push_back(createNonSecureAudioCodecResource());
-        CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+                                            .uid = static_cast<int32_t>(kTestUid2),
+                                            .id = 0,
+                                            .name = "none"};
+        CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Now add an audio codec resource
         std::vector<MediaResourceParcel> audioResources;
         audioResources.push_back(createNonSecureAudioCodecResource());
-        mService->addResource(kLowPriorityPid, kTestUid2, getId(audioTestClient), audioTestClient,
-                audioResources);
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(audioTestClient),
+                                     .name = "none"};
+        mService->addResource(client2Info, audioTestClient, audioResources);
 
         // Verify that the newly-created audio codec resource can be reclaimed
-        CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Verify that the video and image resources are untouched
         EXPECT_FALSE(toTestClient(videoImageTestClient)->checkIfReclaimedAndReset());
@@ -876,22 +988,32 @@
         std::vector<MediaResourceParcel> videoAudioResources;
         videoAudioResources.push_back(createNonSecureVideoCodecResource());
         videoAudioResources.push_back(createNonSecureAudioCodecResource());
-        mService->addResource(kLowPriorityPid, kTestUid1, getId(videoAudioTestClient),
-                videoAudioTestClient, videoAudioResources);
+        ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                     .uid = static_cast<int32_t>(kTestUid1),
+                                     .id = getId(videoAudioTestClient),
+                                     .name = "none"};
+        mService->addResource(client1Info, videoAudioTestClient, videoAudioResources);
 
         // Fail to reclaim an image codec resource
         std::vector<MediaResourceParcel> reclaimResources;
         reclaimResources.push_back(createNonSecureImageCodecResource());
-        CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+                                            .uid = static_cast<int32_t>(kTestUid2),
+                                            .id = 0,
+                                            .name = "none"};
+        CHECK_STATUS_FALSE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Now add an image codec resource
         std::vector<MediaResourceParcel> imageResources;
         imageResources.push_back(createNonSecureImageCodecResource());
-        mService->addResource(kLowPriorityPid, kTestUid2, getId(imageTestClient), imageTestClient,
-                imageResources);
+        ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                     .uid = static_cast<int32_t>(kTestUid2),
+                                     .id = getId(imageTestClient),
+                                     .name = "none"};
+        mService->addResource(client2Info, imageTestClient, imageResources);
 
         // Verify that the newly-created image codec resource can be reclaimed
-        CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Verify that the video and audio resources are untouched
         EXPECT_FALSE(toTestClient(mTestClient1)->checkIfReclaimedAndReset());
@@ -901,20 +1023,27 @@
 
     void testReclaimResources_whenPartialResourceMatch_reclaims() {
         const int onlyUid = kTestUid1;
-        const auto onlyClient = createTestClient(kLowPriorityPid);
+        const auto onlyClient = createTestClient(kLowPriorityPid, onlyUid);
 
         std::vector<MediaResourceParcel> ownedResources;
         ownedResources.push_back(createNonSecureVideoCodecResource());
         ownedResources.push_back(createGraphicMemoryResource(100));
-        mService->addResource(kLowPriorityPid, onlyUid, getId(onlyClient), onlyClient,
-                ownedResources);
+        ClientInfoParcel onlyClientInfo{.pid = static_cast<int32_t>(kLowPriorityPid),
+                                       .uid = static_cast<int32_t>(onlyUid),
+                                       .id = getId(onlyClient),
+                                       .name = "none"};
+        mService->addResource(onlyClientInfo, onlyClient, ownedResources);
 
         // Reclaim an image codec instead of the video codec that is owned, but also reclaim
         // graphics memory, which will trigger the reclaim.
         std::vector<MediaResourceParcel> reclaimResources;
         reclaimResources.push_back(createNonSecureImageCodecResource());
         reclaimResources.push_back(createGraphicMemoryResource(100));
-        CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, reclaimResources, &result));
+        ClientInfoParcel highPriorityClient{.pid = static_cast<int32_t>(kHighPriorityPid),
+                                            .uid = static_cast<int32_t>(kTestUid2),
+                                            .id = 0,
+                                            .name = "none"};
+        CHECK_STATUS_TRUE(mService->reclaimResource(highPriorityClient, reclaimResources, &result));
 
         // Verify that the video codec resources (including the needed graphic memory) is reclaimed
         EXPECT_TRUE(toTestClient(onlyClient)->checkIfReclaimedAndReset());
@@ -926,200 +1055,278 @@
         const int onlyUid = kTestUid1;
 
         // secure video codec
-        const auto smallSecureVideoMarkedClient = createTestClient(onlyPid);
-        const auto largeSecureVideoMarkedClient = createTestClient(onlyPid);
-        const auto largestSecureVideoActiveClient = createTestClient(onlyPid);
+        const auto smallSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestSecureVideoActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientA{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallSecureVideoMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientB{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeSecureVideoMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientC{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestSecureVideoActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createSecureVideoCodecResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallSecureVideoMarkedClient),
-                    smallSecureVideoMarkedClient, resources);
+            mService->addResource(clientA, smallSecureVideoMarkedClient, resources);
             resources.clear();
             resources.push_back(createSecureVideoCodecResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeSecureVideoMarkedClient),
-                    largeSecureVideoMarkedClient, resources);
+            mService->addResource(clientB, largeSecureVideoMarkedClient, resources);
             resources.clear();
             resources.push_back(createSecureVideoCodecResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestSecureVideoActiveClient),
-                    largestSecureVideoActiveClient, resources);
+            mService->addResource(clientC, largestSecureVideoActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallSecureVideoMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeSecureVideoMarkedClient));
+        mService->markClientForPendingRemoval(clientA);
+        mService->markClientForPendingRemoval(clientB);
         // don't mark the largest client
 
         // non-secure video codec
-        const auto smallNonSecureVideoMarkedClient = createTestClient(onlyPid);
-        const auto largeNonSecureVideoMarkedClient = createTestClient(onlyPid);
-        const auto largestNonSecureVideoActiveClient = createTestClient(onlyPid);
+        const auto smallNonSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeNonSecureVideoMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestNonSecureVideoActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientD{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallNonSecureVideoMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientE{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeNonSecureVideoMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientF{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestNonSecureVideoActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createNonSecureVideoCodecResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallNonSecureVideoMarkedClient),
-                    smallNonSecureVideoMarkedClient, resources);
+            mService->addResource(clientD, smallNonSecureVideoMarkedClient, resources);
             resources.clear();
             resources.push_back(createNonSecureVideoCodecResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeNonSecureVideoMarkedClient),
-                    largeNonSecureVideoMarkedClient, resources);
+            mService->addResource(clientE, largeNonSecureVideoMarkedClient, resources);
             resources.clear();
             resources.push_back(createNonSecureVideoCodecResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestNonSecureVideoActiveClient),
-                    largestNonSecureVideoActiveClient, resources);
+            mService->addResource(clientF, largestNonSecureVideoActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureVideoMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureVideoMarkedClient));
+        mService->markClientForPendingRemoval(clientD);
+        mService->markClientForPendingRemoval(clientE);
         // don't mark the largest client
 
         // secure audio codec
-        const auto smallSecureAudioMarkedClient = createTestClient(onlyPid);
-        const auto largeSecureAudioMarkedClient = createTestClient(onlyPid);
-        const auto largestSecureAudioActiveClient = createTestClient(onlyPid);
+        const auto smallSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestSecureAudioActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientG{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallSecureAudioMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientH{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeSecureAudioMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientI{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestSecureVideoActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createSecureAudioCodecResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallSecureAudioMarkedClient),
-                    smallSecureAudioMarkedClient, resources);
+            mService->addResource(clientG, smallSecureAudioMarkedClient, resources);
             resources.clear();
             resources.push_back(createSecureAudioCodecResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeSecureAudioMarkedClient),
-                    largeSecureAudioMarkedClient, resources);
+            mService->addResource(clientH, largeSecureAudioMarkedClient, resources);
             resources.clear();
             resources.push_back(createSecureAudioCodecResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestSecureVideoActiveClient),
-                    largestSecureVideoActiveClient, resources);
+            mService->addResource(clientI, largestSecureVideoActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallSecureAudioMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeSecureAudioMarkedClient));
+        mService->markClientForPendingRemoval(clientG);
+        mService->markClientForPendingRemoval(clientH);
         // don't mark the largest client
 
         // non-secure audio codec
-        const auto smallNonSecureAudioMarkedClient = createTestClient(onlyPid);
-        const auto largeNonSecureAudioMarkedClient = createTestClient(onlyPid);
-        const auto largestNonSecureAudioActiveClient = createTestClient(onlyPid);
+        const auto smallNonSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeNonSecureAudioMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestNonSecureAudioActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientJ{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallNonSecureAudioMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientK{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeNonSecureAudioMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientL{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestNonSecureAudioActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createNonSecureAudioCodecResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallNonSecureAudioMarkedClient),
-                    smallNonSecureAudioMarkedClient, resources);
+            mService->addResource(clientJ, smallNonSecureAudioMarkedClient, resources);
             resources.clear();
             resources.push_back(createNonSecureAudioCodecResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeNonSecureAudioMarkedClient),
-                    largeNonSecureAudioMarkedClient, resources);
+            mService->addResource(clientK, largeNonSecureAudioMarkedClient, resources);
             resources.clear();
             resources.push_back(createNonSecureAudioCodecResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestNonSecureAudioActiveClient),
-                    largestNonSecureAudioActiveClient, resources);
+            mService->addResource(clientL, largestNonSecureAudioActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureAudioMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureAudioMarkedClient));
+        mService->markClientForPendingRemoval(clientJ);
+        mService->markClientForPendingRemoval(clientK);
         // don't mark the largest client
 
         // secure image codec
-        const auto smallSecureImageMarkedClient = createTestClient(onlyPid);
-        const auto largeSecureImageMarkedClient = createTestClient(onlyPid);
-        const auto largestSecureImageActiveClient = createTestClient(onlyPid);
+        const auto smallSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestSecureImageActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientM{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallSecureImageMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientN{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeSecureImageMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientO{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestSecureImageActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createSecureImageCodecResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallSecureImageMarkedClient),
-                    smallSecureImageMarkedClient, resources);
+            mService->addResource(clientM, smallSecureImageMarkedClient, resources);
             resources.clear();
             resources.push_back(createSecureImageCodecResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeSecureImageMarkedClient),
-                    largeSecureImageMarkedClient, resources);
+            mService->addResource(clientN, largeSecureImageMarkedClient, resources);
             resources.clear();
             resources.push_back(createSecureImageCodecResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestSecureImageActiveClient),
-                    largestSecureImageActiveClient, resources);
+            mService->addResource(clientO, largestSecureImageActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallSecureImageMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeSecureImageMarkedClient));
+        mService->markClientForPendingRemoval(clientM);
+        mService->markClientForPendingRemoval(clientN);
         // don't mark the largest client
 
         // non-secure image codec
-        const auto smallNonSecureImageMarkedClient = createTestClient(onlyPid);
-        const auto largeNonSecureImageMarkedClient = createTestClient(onlyPid);
-        const auto largestNonSecureImageActiveClient = createTestClient(onlyPid);
+        const auto smallNonSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeNonSecureImageMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestNonSecureImageActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientP{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallNonSecureImageMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientQ{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeNonSecureImageMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientR{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestNonSecureImageActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createNonSecureImageCodecResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallNonSecureImageMarkedClient),
-                    smallNonSecureImageMarkedClient, resources);
+            mService->addResource(clientP, smallNonSecureImageMarkedClient, resources);
             resources.clear();
             resources.push_back(createNonSecureImageCodecResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeNonSecureImageMarkedClient),
-                    largeNonSecureImageMarkedClient, resources);
+            mService->addResource(clientQ, largeNonSecureImageMarkedClient, resources);
             resources.clear();
             resources.push_back(createNonSecureImageCodecResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestNonSecureImageActiveClient),
-                    largestNonSecureImageActiveClient, resources);
+            mService->addResource(clientR, largestNonSecureImageActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallNonSecureImageMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeNonSecureImageMarkedClient));
+        mService->markClientForPendingRemoval(clientP);
+        mService->markClientForPendingRemoval(clientQ);
         // don't mark the largest client
 
         // graphic memory
-        const auto smallGraphicMemoryMarkedClient = createTestClient(onlyPid);
-        const auto largeGraphicMemoryMarkedClient = createTestClient(onlyPid);
-        const auto largestGraphicMemoryActiveClient = createTestClient(onlyPid);
+        const auto smallGraphicMemoryMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeGraphicMemoryMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestGraphicMemoryActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientS{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallGraphicMemoryMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientT{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeGraphicMemoryMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientU{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestGraphicMemoryActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createGraphicMemoryResource(100));
-            mService->addResource(onlyPid, onlyUid, getId(smallGraphicMemoryMarkedClient),
-                    smallGraphicMemoryMarkedClient, resources);
+            mService->addResource(clientS, smallGraphicMemoryMarkedClient, resources);
             resources.clear();
             resources.push_back(createGraphicMemoryResource(200));
-            mService->addResource(onlyPid, onlyUid, getId(largeGraphicMemoryMarkedClient),
-                    largeGraphicMemoryMarkedClient, resources);
+            mService->addResource(clientT, largeGraphicMemoryMarkedClient, resources);
             resources.clear();
             resources.push_back(createGraphicMemoryResource(300));
-            mService->addResource(onlyPid, onlyUid, getId(largestGraphicMemoryActiveClient),
-                    largestGraphicMemoryActiveClient, resources);
+            mService->addResource(clientU, largestGraphicMemoryActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallGraphicMemoryMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeGraphicMemoryMarkedClient));
+        mService->markClientForPendingRemoval(clientS);
+        mService->markClientForPendingRemoval(clientT);
         // don't mark the largest client
 
         // DRM session
-        const auto smallDrmSessionMarkedClient = createTestClient(onlyPid);
-        const auto largeDrmSessionMarkedClient = createTestClient(onlyPid);
-        const auto largestDrmSessionActiveClient = createTestClient(onlyPid);
+        const auto smallDrmSessionMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largeDrmSessionMarkedClient = createTestClient(onlyPid, onlyUid);
+        const auto largestDrmSessionActiveClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientV{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(smallDrmSessionMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientW{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largeDrmSessionMarkedClient),
+                                 .name = "none"};
+        ClientInfoParcel clientX{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(largestDrmSessionActiveClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createDrmSessionResource(1));
-            mService->addResource(onlyPid, onlyUid, getId(smallDrmSessionMarkedClient),
-                    smallDrmSessionMarkedClient, resources);
+            mService->addResource(clientV, smallDrmSessionMarkedClient, resources);
             resources.clear();
             resources.push_back(createDrmSessionResource(2));
-            mService->addResource(onlyPid, onlyUid, getId(largeDrmSessionMarkedClient),
-                    largeDrmSessionMarkedClient, resources);
+            mService->addResource(clientW, largeDrmSessionMarkedClient, resources);
             resources.clear();
             resources.push_back(createDrmSessionResource(3));
-            mService->addResource(onlyPid, onlyUid, getId(largestDrmSessionActiveClient),
-                    largestDrmSessionActiveClient, resources);
+            mService->addResource(clientX, largestDrmSessionActiveClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(smallDrmSessionMarkedClient));
-        mService->markClientForPendingRemoval(onlyPid, getId(largeDrmSessionMarkedClient));
+        mService->markClientForPendingRemoval(clientV);
+        mService->markClientForPendingRemoval(clientW);
         // don't mark the largest client
 
         // battery
-        const auto batteryMarkedClient = createTestClient(onlyPid);
+        const auto batteryMarkedClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientY{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(batteryMarkedClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createBatteryResource());
-            mService->addResource(onlyPid, onlyUid, getId(batteryMarkedClient),
-                    batteryMarkedClient, resources);
+            mService->addResource(clientY, batteryMarkedClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(batteryMarkedClient));
+        mService->markClientForPendingRemoval(clientY);
 
         // CPU boost
-        const auto cpuBoostMarkedClient = createTestClient(onlyPid);
+        const auto cpuBoostMarkedClient = createTestClient(onlyPid, onlyUid);
+        ClientInfoParcel clientZ{.pid = static_cast<int32_t>(onlyPid),
+                                 .uid = static_cast<int32_t>(onlyUid),
+                                 .id = getId(cpuBoostMarkedClient),
+                                 .name = "none"};
         {
             std::vector<MediaResourceParcel> resources;
             resources.push_back(createCpuBoostResource());
-            mService->addResource(onlyPid, onlyUid, getId(cpuBoostMarkedClient),
-                    cpuBoostMarkedClient, resources);
+            mService->addResource(clientZ, cpuBoostMarkedClient, resources);
         }
-        mService->markClientForPendingRemoval(onlyPid, getId(cpuBoostMarkedClient));
+        mService->markClientForPendingRemoval(clientZ);
 
         // now we expect that we only reclaim resources from the biggest marked client
         EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(onlyPid).isOk());
diff --git a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
index 003569d..a0d728c 100644
--- a/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceObserverService_test.cpp
@@ -251,17 +251,31 @@
     observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
                    {MediaObservableType::kVideoNonSecureCodec, 1}};
 
+    ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                 .uid = static_cast<int32_t>(kTestUid1),
+                                 .id = getId(mTestClient1),
+                                 .name = "none"};
+
+    ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient2),
+                                 .name = "none"};
+
+    ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient3),
+                                 .name = "none"};
     std::vector<MediaResourceParcel> resources;
     // Add secure video codec.
     resources = {createSecureVideoCodecResource()};
-    mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+    mService->addResource(client1Info, mTestClient1, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
 
     // Add non-secure video codec.
     resources = {createNonSecureVideoCodecResource()};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources);
+    mService->addResource(client2Info, mTestClient2, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
@@ -269,7 +283,7 @@
     // Add secure & non-secure video codecs.
     resources = {createSecureVideoCodecResource(),
                  createNonSecureVideoCodecResource()};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+    mService->addResource(client3Info, mTestClient3, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
@@ -277,7 +291,7 @@
     // Add additional audio codecs, should be ignored.
     resources.push_back(createSecureAudioCodecResource());
     resources.push_back(createNonSecureAudioCodecResource());
-    mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+    mService->addResource(client1Info, mTestClient1, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables3));
@@ -303,7 +317,11 @@
     observables2 = {{MediaObservableType::kVideoNonSecureCodec, 3}};
     observables3 = {{MediaObservableType::kVideoSecureCodec, 2},
                    {MediaObservableType::kVideoNonSecureCodec, 3}};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+    ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient3),
+                                 .name = "none"};
+    mService->addResource(client3Info, mTestClient3, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
@@ -318,47 +336,61 @@
     observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
                    {MediaObservableType::kVideoNonSecureCodec, 1}};
 
+    ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                 .uid = static_cast<int32_t>(kTestUid1),
+                                 .id = getId(mTestClient1),
+                                 .name = "none"};
+
+    ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient2),
+                                 .name = "none"};
+
+    ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient3),
+                                 .name = "none"};
     std::vector<MediaResourceParcel> resources;
     // Add secure video codec to client1.
     resources = {createSecureVideoCodecResource()};
-    mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources);
+    mService->addResource(client1Info, mTestClient1, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid1, kTestPid1, observables1));
     // Remove secure video codec. observer 1&3 should receive updates.
-    mService->removeResource(kTestPid1, getId(mTestClient1), resources);
+    mService->removeResource(client1Info, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid1, kTestPid1, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid1, kTestPid1, observables1));
     // Remove secure video codec again, should have no event.
-    mService->removeResource(kTestPid1, getId(mTestClient1), resources);
+    mService->removeResource(client1Info, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
     // Remove client1, should have no event.
-    mService->removeClient(kTestPid1, getId(mTestClient1));
+    mService->removeClient(client1Info);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
 
     // Add non-secure video codec to client2.
     resources = {createNonSecureVideoCodecResource()};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources);
+    mService->addResource(client2Info, mTestClient2, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
     // Remove client2, observer 2&3 should receive updates.
-    mService->removeClient(kTestPid2, getId(mTestClient2));
+    mService->removeClient(client2Info);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
     // Remove non-secure codec after client2 removed, should have no event.
-    mService->removeResource(kTestPid2, getId(mTestClient2), resources);
+    mService->removeResource(client2Info, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
     // Remove client2 again, should have no event.
-    mService->removeClient(kTestPid2, getId(mTestClient2));
+    mService->removeClient(client2Info);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
@@ -368,13 +400,13 @@
                  createNonSecureVideoCodecResource(),
                  createSecureAudioCodecResource(),
                  createNonSecureAudioCodecResource()};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+    mService->addResource(client3Info, mTestClient3, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables3));
     // Remove one audio codec, should have no event.
     resources = {createSecureAudioCodecResource()};
-    mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+    mService->removeResource(client3Info, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::NoEvent);
@@ -382,12 +414,12 @@
     // removal should be reported.
     resources = {createNonSecureAudioCodecResource(),
                  createSecureVideoCodecResource()};
-    mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+    mService->removeResource(client3Info, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
     // Remove client3 entirely. Non-secure video codec removal should be reported.
-    mService->removeClient(kTestPid2, getId(mTestClient3));
+    mService->removeClient(client3Info);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
@@ -410,7 +442,12 @@
                  createNonSecureVideoCodecResource(4),
                  createSecureAudioCodecResource(),
                  createNonSecureAudioCodecResource()};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+
+    ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient3),
+                                 .name = "none"};
+    mService->addResource(client3Info, mTestClient3, resources);
     observables1 = {{MediaObservableType::kVideoSecureCodec, 1}};
     observables2 = {{MediaObservableType::kVideoNonSecureCodec, 4}};
     observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
@@ -424,7 +461,7 @@
                  createSecureVideoCodecResource(),
                  createSecureVideoCodecResource(),
                  createNonSecureVideoCodecResource(2)};
-    mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+    mService->removeResource(client3Info, resources);
     observables1 = {{MediaObservableType::kVideoSecureCodec, 1}};
     observables2 = {{MediaObservableType::kVideoNonSecureCodec, 2}};
     observables3 = {{MediaObservableType::kVideoSecureCodec, 1},
@@ -433,7 +470,7 @@
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables3));
     // Remove client3 entirely. 2 non-secure video codecs removal should be reported.
-    mService->removeClient(kTestPid2, getId(mTestClient3));
+    mService->removeClient(client3Info);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
@@ -465,13 +502,27 @@
     // Add secure & non-secure video codecs.
     resources = {createSecureVideoCodecResource(),
                  createNonSecureVideoCodecResource()};
-    mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources);
+    ClientInfoParcel client1Info{.pid = static_cast<int32_t>(kTestPid1),
+                                 .uid = static_cast<int32_t>(kTestUid1),
+                                 .id = getId(mTestClient1),
+                                 .name = "none"};
+
+    ClientInfoParcel client2Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient2),
+                                 .name = "none"};
+
+    ClientInfoParcel client3Info{.pid = static_cast<int32_t>(kTestPid2),
+                                 .uid = static_cast<int32_t>(kTestUid2),
+                                 .id = getId(mTestClient3),
+                                 .name = "none"};
+    mService->addResource(client3Info, mTestClient3, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables1));
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Busy(kTestUid2, kTestPid2, observables2));
 
     // Remove secure & non-secure video codecs.
-    mService->removeResource(kTestPid2, getId(mTestClient3), resources);
+    mService->removeResource(client3Info, resources);
     EXPECT_EQ(mTestObserver1->pop(), EventTracker::NoEvent);
     EXPECT_EQ(mTestObserver2->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables2));
     EXPECT_EQ(mTestObserver3->pop(), EventTracker::Idle(kTestUid2, kTestPid2, observables1));
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index 80e4296..5076239 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -25,6 +25,10 @@
 
     name: "libaaudioservice",
 
+    defaults: [
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
     srcs: [
         "AAudioClientTracker.cpp",
         "AAudioCommandQueue.cpp",
@@ -70,7 +74,6 @@
         "framework-permission-aidl-cpp",
         "libaudioclient_aidl_conversion",
         "packagemanager_aidl-cpp",
-        "android.media.audio.common.types-V1-cpp",
     ],
 
     export_shared_lib_headers: [
diff --git a/services/tuner/hidl/TunerHidlDvr.cpp b/services/tuner/hidl/TunerHidlDvr.cpp
index 1a619d5..3ea1eb1 100644
--- a/services/tuner/hidl/TunerHidlDvr.cpp
+++ b/services/tuner/hidl/TunerHidlDvr.cpp
@@ -72,7 +72,7 @@
 
     AidlMQDesc aidlMQDesc;
     unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(dvrMQDesc, &aidlMQDesc);
-    *_aidl_return = move(aidlMQDesc);
+    *_aidl_return = std::move(aidlMQDesc);
     return ::ndk::ScopedAStatus::ok();
 }
 
diff --git a/services/tuner/hidl/TunerHidlFilter.cpp b/services/tuner/hidl/TunerHidlFilter.cpp
index fe74a5c..c82732b 100644
--- a/services/tuner/hidl/TunerHidlFilter.cpp
+++ b/services/tuner/hidl/TunerHidlFilter.cpp
@@ -139,7 +139,7 @@
 
     AidlMQDesc aidlMQDesc;
     unsafeHidlToAidlMQDescriptor<uint8_t, int8_t, SynchronizedReadWrite>(filterMQDesc, &aidlMQDesc);
-    *_aidl_return = move(aidlMQDesc);
+    *_aidl_return = std::move(aidlMQDesc);
 
     return ::ndk::ScopedAStatus::ok();
 }
@@ -1084,8 +1084,8 @@
         }
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::media>(move(media));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::media>(std::move(media));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1101,8 +1101,8 @@
         section.dataLength = static_cast<int64_t>(sectionEvent.dataLength);
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::section>(move(section));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::section>(std::move(section));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1117,8 +1117,8 @@
         pes.mpuSequenceNumber = static_cast<int32_t>(pesEvent.mpuSequenceNumber);
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::pes>(move(pes));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::pes>(std::move(pes));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1167,8 +1167,8 @@
         }
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::tsRecord>(move(tsRecord));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::tsRecord>(std::move(tsRecord));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1194,8 +1194,8 @@
         }
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::mmtpRecord>(move(mmtpRecord));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::mmtpRecord>(std::move(mmtpRecord));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1213,8 +1213,8 @@
         download.dataLength = static_cast<int32_t>(downloadEvent.dataLength);
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::download>(move(download));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::download>(std::move(download));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1227,8 +1227,8 @@
         ipPayload.dataLength = static_cast<int32_t>(ipPayloadEvent.dataLength);
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::ipPayload>(move(ipPayload));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::ipPayload>(std::move(ipPayload));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1245,8 +1245,8 @@
         copy(descrData.begin(), descrData.end(), temi.descrData.begin());
 
         DemuxFilterEvent filterEvent;
-        filterEvent.set<DemuxFilterEvent::temi>(move(temi));
-        res.push_back(move(filterEvent));
+        filterEvent.set<DemuxFilterEvent::temi>(std::move(temi));
+        res.push_back(std::move(filterEvent));
     }
 }
 
@@ -1268,15 +1268,15 @@
     }
 
     DemuxFilterEvent filterEvent;
-    filterEvent.set<DemuxFilterEvent::monitorEvent>(move(monitor));
-    res.push_back(move(filterEvent));
+    filterEvent.set<DemuxFilterEvent::monitorEvent>(std::move(monitor));
+    res.push_back(std::move(filterEvent));
 }
 
 void TunerHidlFilter::FilterCallback::getRestartEvent(
         const vector<HidlDemuxFilterEventExt::Event>& eventsExt, vector<DemuxFilterEvent>& res) {
     DemuxFilterEvent filterEvent;
     filterEvent.set<DemuxFilterEvent::startId>(static_cast<int32_t>(eventsExt[0].startId()));
-    res.push_back(move(filterEvent));
+    res.push_back(std::move(filterEvent));
 }
 
 }  // namespace tuner
diff --git a/tools/OWNERS b/tools/OWNERS
new file mode 100644
index 0000000..7598c6f
--- /dev/null
+++ b/tools/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 1344
+essick@google.com
+
+# reliability builds mainline trains, so needs to manage these scripts
+include platform/frameworks/av/:/media/janitors/reliability_mainline_OWNERS
diff --git a/tools/mainline_hook_partial.sh b/tools/mainline_hook_partial.sh
index bd82315..cd3e579 100755
--- a/tools/mainline_hook_partial.sh
+++ b/tools/mainline_hook_partial.sh
Binary files differ
diff --git a/tools/mainline_hook_project.sh b/tools/mainline_hook_project.sh
index cb5fc44..1cc3b2b 100755
--- a/tools/mainline_hook_project.sh
+++ b/tools/mainline_hook_project.sh
@@ -17,7 +17,7 @@
 
 # tunables
 DEV_BRANCH=master
-MAINLINE_BRANCH=sc-mainline-prod
+MAINLINE_BRANCH=tm-mainline-prod
 
 ###
 RED=$(tput setaf 1)